From 39d87dc8f330efde99360e6438f7b8f167fda19d Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Wed, 17 Jun 2026 16:32:49 +0200 Subject: [PATCH 1/7] Half done --- .../details/daemon/AliveMonitorImpl.cpp | 10 +- .../src/alive_monitor/details/daemon/BUILD | 3 + .../details/daemon/PhmDaemon.cpp | 5 +- .../details/daemon/PhmDaemon.hpp | 11 +- .../details/daemon/SwClusterHandler.cpp | 6 +- .../details/daemon/SwClusterHandler.hpp | 27 +- .../src/alive_monitor/details/factory/BUILD | 6 +- .../details/factory/FlatCfgFactory.cpp | 331 +++---- .../details/factory/FlatCfgFactory.hpp | 33 +- .../details/factory/MachineConfigFactory.cpp | 133 +-- .../details/factory/MachineConfigFactory.hpp | 41 +- .../daemon/src/configuration/BUILD | 12 +- .../configuration/configuration_adapter.cpp | 421 +++++++++ .../configuration/configuration_adapter.hpp | 125 +++ .../configuration/configuration_manager.cpp | 883 ------------------ .../configuration/configuration_manager.hpp | 485 ---------- .../daemon/src/process_group_manager/BUILD | 2 +- .../src/process_group_manager/details/BUILD | 6 +- .../process_group_manager/details/graph.cpp | 6 +- .../process_group_manager/details/graph.hpp | 2 +- .../details/process_group_manager.cpp | 30 +- .../details/process_info_node.cpp | 4 +- .../details/process_info_node.hpp | 2 +- .../process_group_manager.hpp | 16 +- scripts/config_mapping/config.bzl | 63 +- scripts/config_mapping/integration_tests.py | 8 +- scripts/config_mapping/lifecycle_config.py | 645 +++++-------- .../basic_test/expected_output/hm_demo.json | 102 -- .../basic_test/expected_output/hmcore.json | 20 - .../launch_manager_config.json | 373 ++++++++ .../basic_test/expected_output/lm_demo.json | 376 -------- .../expected_output/hm_demo.json | 8 - .../expected_output/hmcore.json | 10 - .../launch_manager_config.json | 74 ++ .../expected_output/hm_demo.json | 8 - .../expected_output/hmcore.json | 20 - .../launch_manager_config.json | 28 + .../expected_output/lm_demo.json | 20 - .../expected_output/hm_demo.json | 102 -- .../expected_output/hmcore.json | 20 - .../launch_manager_config.json | 217 +++++ .../expected_output/hm_demo.json | 132 --- .../expected_output/hmcore.json | 20 - .../launch_manager_config.json | 445 +++++++++ .../expected_output/lm_demo.json | 453 --------- 45 files changed, 2147 insertions(+), 3597 deletions(-) create mode 100644 score/launch_manager/daemon/src/configuration/configuration_adapter.cpp create mode 100644 score/launch_manager/daemon/src/configuration/configuration_adapter.hpp delete mode 100644 score/launch_manager/daemon/src/configuration/configuration_manager.cpp delete mode 100644 score/launch_manager/daemon/src/configuration/configuration_manager.hpp delete mode 100644 scripts/config_mapping/tests/basic_test/expected_output/hm_demo.json delete mode 100644 scripts/config_mapping/tests/basic_test/expected_output/hmcore.json create mode 100644 scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json delete mode 100644 scripts/config_mapping/tests/basic_test/expected_output/lm_demo.json delete mode 100644 scripts/config_mapping/tests/empty_health_config_test/expected_output/hm_demo.json delete mode 100644 scripts/config_mapping/tests/empty_health_config_test/expected_output/hmcore.json create mode 100644 scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json delete mode 100644 scripts/config_mapping/tests/empty_lm_config_test/expected_output/hm_demo.json delete mode 100644 scripts/config_mapping/tests/empty_lm_config_test/expected_output/hmcore.json create mode 100644 scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json delete mode 100644 scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_demo.json delete mode 100644 scripts/config_mapping/tests/health_config_test/expected_output/hm_demo.json delete mode 100644 scripts/config_mapping/tests/health_config_test/expected_output/hmcore.json create mode 100644 scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json delete mode 100644 scripts/config_mapping/tests/lm_config_test/expected_output/hm_demo.json delete mode 100644 scripts/config_mapping/tests/lm_config_test/expected_output/hmcore.json create mode 100644 scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json delete mode 100644 scripts/config_mapping/tests/lm_config_test/expected_output/lm_demo.json diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp index 79964286f..de9048508 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp @@ -18,6 +18,7 @@ #include "score/mw/launch_manager/alive_monitor/details/daemon/AliveMonitorImpl.hpp" #include "score/mw/launch_manager/alive_monitor/details/logging/PhmLogger.hpp" #include "score/mw/launch_manager/alive_monitor/details/watchdog/WatchdogImpl.hpp" +#include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" namespace score { namespace lcm { @@ -32,8 +33,15 @@ EInitCode AliveMonitorImpl::init() noexcept { try { m_osClock.startMeasurement(); + score::mw::launch_manager::configuration::FlatbufferConfigLoader loader; + auto config_result = loader.load("etc/launch_manager_config.bin"); + if (!config_result.has_value()) { + m_logger.LogError() << "HealthMonitor: Failed to load launch_manager_config.bin"; + return EInitCode::kGeneralError; + } + m_daemon = std::make_unique(m_osClock, m_logger, std::move(m_watchdog), std::move(m_process_state_receiver)); - initResult = m_daemon->init(m_recovery_client); + initResult = m_daemon->init(m_recovery_client, *config_result); if (initResult == score::lcm::saf::daemon::EInitCode::kNoError) { const long ms{m_osClock.endMeasurement()}; diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD b/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD index 5b767374c..82149e336 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD @@ -38,6 +38,7 @@ cc_library( "//score/launch_manager/daemon/src/alive_monitor/details/logging:phm_logging", "//score/launch_manager/daemon/src/alive_monitor/details/supervision:alive", "//score/launch_manager/daemon/src/alive_monitor/details/timers:timers_os_clock", + "//score/launch_manager/daemon/src/configuration:config", ], ) @@ -62,6 +63,7 @@ cc_library( "//score/launch_manager/daemon/src/alive_monitor/details/timers:cycle_timer", "//score/launch_manager/daemon/src/alive_monitor/details/timers:timers_os_clock", "//score/launch_manager/daemon/src/alive_monitor/details/watchdog:i_watchdog_if", + "//score/launch_manager/daemon/src/configuration:config", "//score/launch_manager/lifecycle_client", ], ) @@ -86,5 +88,6 @@ cc_library( ":i_health_monitor", "//score/launch_manager/daemon/src/alive_monitor/details/logging:phm_logging", "//score/launch_manager/daemon/src/alive_monitor/details/watchdog:watchdog_impl", + "//score/launch_manager/daemon/src/configuration:flatbuffer_config_loader", ], ) diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp index bc8fef0e7..b64e6f2e3 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.cpp @@ -82,7 +82,8 @@ void PhmDaemon::performCyclicTriggers(void) } } -bool PhmDaemon::construct(const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept( +bool PhmDaemon::construct(const score::mw::launch_manager::configuration::Config& config, + const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept( false) { bool isSuccess{true}; @@ -108,7 +109,7 @@ bool PhmDaemon::construct(const factory::MachineConfigFactory::SupervisionBuffer for (auto strSwClusterName : listSwClustersPhm.value()) { swClusterHandlers.emplace_back(strSwClusterName); - isSuccess = swClusterHandlers.back().constructWorkers(recoveryClient, processStateReader, f_bufferConfig_r); + isSuccess = swClusterHandlers.back().constructWorkers(config, recoveryClient, processStateReader, f_bufferConfig_r); if (!isSuccess) { logger_r.LogError() << "Phm Daemon: failed to create worker objects for swclusterhandler:" diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp index 547601a9e..d521a531e 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/PhmDaemon.hpp @@ -29,6 +29,7 @@ #include "score/mw/launch_manager/alive_monitor/details/timers/CycleTimeValidator.hpp" #include "score/mw/launch_manager/alive_monitor/details/timers/CycleTimer.hpp" #include "score/mw/launch_manager/alive_monitor/details/watchdog/IWatchdogIf.hpp" +#include "score/mw/launch_manager/configuration/config.hpp" namespace score { namespace lcm @@ -90,17 +91,18 @@ class PhmDaemon /// (Constructing the workers, adjusting the cycle time, initialization of fixed step timer) /// @param[in] recovery_client Shared pointer to recovery client /// @return See EInitCode definition - EInitCode init(std::shared_ptr recovery_client) noexcept(false) + EInitCode init(std::shared_ptr recovery_client, + const score::mw::launch_manager::configuration::Config& config) noexcept(false) { recoveryClient = recovery_client; factory::MachineConfigFactory machineConfig{}; - if (!machineConfig.init()) + if (!machineConfig.init(config)) { return EInitCode::kMachineConfigInitFailed; } - if (!construct(machineConfig.getSupervisionBufferConfig())) + if (!construct(config, machineConfig.getSupervisionBufferConfig())) { return EInitCode::kConstructFlatCfgFactoryFailed; } @@ -218,7 +220,8 @@ class PhmDaemon /// @details Create the SwclusterHandler objects and the workers for the SwclusterHandler /// @param[in] f_bufferConfig_r The buffer configuration used for worker construction /// @return bool true if workers creation succeeded, false otherwise - bool construct(const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept(false); + bool construct(const score::mw::launch_manager::configuration::Config& config, + const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept(false); /// @brief Perform cyclic execution of Phm daemon /// @details Perform cyclic execution of Phm daemon functionalities, for e.g., evaluation of supervisions. diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.cpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.cpp index 5a5643465..baa85fad4 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.cpp @@ -44,9 +44,8 @@ SwClusterHandler::SwClusterHandler(const std::string& f_swClusterName_r) SwClusterHandler::~SwClusterHandler() = default; -/* RULECHECKER_comment(0, 3, check_max_cyclomatic_complexity, "Max cyclomatic complexity violation\ - is tolerated for this function. ", true_no_defect) */ bool SwClusterHandler::constructWorkers( + const score::mw::launch_manager::configuration::Config& config, std::shared_ptr f_recoveryClient_r, ifexm::ProcessStateReader& f_processStateReader_r, const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept(false) @@ -54,8 +53,7 @@ bool SwClusterHandler::constructWorkers( bool isSuccess{false}; factory::FlatCfgFactory flatCfgFactory{f_bufferConfig_r}; - const std::string filename = "hm_demo.bin"; - isSuccess = flatCfgFactory.init(filename); + isSuccess = flatCfgFactory.init(config); if (isSuccess) { logger_r.LogDebug() << "Software Cluster Handler starts constructing workers:" << f_swClusterName; diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp index dec198d70..2812d6079 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp @@ -20,6 +20,7 @@ #include "score/mw/launch_manager/alive_monitor/details/ifexm/ProcessStateReader.hpp" #include "score/mw/launch_manager/alive_monitor/details/logging/PhmLogger.hpp" #include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" +#include "score/mw/launch_manager/configuration/config.hpp" #include #include @@ -52,8 +53,6 @@ namespace daemon /// @brief Software Cluster Handler wraps the full PHM Supervision and Recovery Notification functionality for one /// Software Cluster. -/// @details This class requests construction of all required objects to do the Supervisions and Recovery Notifications -/// for a given Software Cluster. It also provides an abstracted interface to trigger the cyclic evaluation. class SwClusterHandler { public: @@ -74,46 +73,26 @@ class SwClusterHandler SwClusterHandler& operator=(const SwClusterHandler&) = delete; /// @brief Move Constructor - /* RULECHECKER_comment(0, 7, check_min_instructions, "Default constructor is not provided\ - a function body", true_no_defect) */ - /* RULECHECKER_comment(0, 5, check_incomplete_data_member_construction, "Default constructor is not provided\ - the member initializer", false) */ - /* RULECHECKER_comment(0, 46, check_copy_in_move_constructor, "The default move constructor invokes parameterised\ - constructor internally. This invokes std::string copy construction", true_no_defect) */ SwClusterHandler(SwClusterHandler&&) = default; /// @brief No Move Assignment SwClusterHandler& operator=(SwClusterHandler&&) = delete; - /// @brief Construct required worker objects for the Software Cluster - /// @details Construct the interfaces, checkpoints, supervisions and recovery notifications - /// @param [in] f_recoveryClient_r Interface to the launch manager for recovery - /// @param [in] f_processStateReader_r Process state reader object for PHM daemon - /// @param [in] f_bufferConfig_r Configuration settings for constructing workers - /// @return Construction is successful (true), otherwise failure (false) + /// @brief Construct required worker objects from the unified Config bool constructWorkers( + const score::mw::launch_manager::configuration::Config& config, std::shared_ptr f_recoveryClient_r, ifexm::ProcessStateReader& f_processStateReader_r, const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept(false); /// @brief Perform cyclic execution - /// @details Perform cyclic execution required for supervision of the Software Cluster - /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void performCyclicTriggers(const timers::NanoSecondType f_syncTimestamp); /// @brief Check whether any alive supervision failed to enqueue a recovery request - /// @return True if any alive supervision recovery request has failed bool hasAnyRecoveryEnqueueFailed() const noexcept; private: - /// @brief Check interfaces for new data - /// @details All interfaces created during construction will be checked for new data. - /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void checkInterfaceForNewData(const timers::NanoSecondType f_syncTimestamp); - - /// @brief Evaluate supervisions - /// @details Evaluate all supervisions created during construction. - /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void evaluateSupervisions(const timers::NanoSecondType f_syncTimestamp); /// @brief Logger diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD b/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD index 8ecfb62cd..25092b12c 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD @@ -45,12 +45,11 @@ cc_library( visibility = ["//score/launch_manager/daemon/src/alive_monitor:__subpackages__"], deps = [ ":static_config", - "//score/launch_manager/daemon/src/alive_monitor:config", "//score/launch_manager/daemon/src/alive_monitor/details/logging:phm_logging", "//score/launch_manager/daemon/src/alive_monitor/details/timers:time_conversion", "//score/launch_manager/daemon/src/alive_monitor/details/timers:timers_os_clock", "//score/launch_manager/daemon/src/alive_monitor/details/watchdog:i_device_config_factory", - "@flatbuffers", + "//score/launch_manager/daemon/src/configuration:config", ] + select({ "@platforms//os:qnx": [], "@platforms//os:linux": ["//externals/acl"], @@ -67,7 +66,6 @@ cc_library( deps = [ ":i_phm_factory", ":machine_config_factory", - "//score/launch_manager/daemon/src/alive_monitor:config", "//score/launch_manager/daemon/src/alive_monitor/details/common:types", "//score/launch_manager/daemon/src/alive_monitor/details/ifappl:checkpoint", "//score/launch_manager/daemon/src/alive_monitor/details/ifappl:monitor_if_daemon", @@ -79,7 +77,7 @@ cc_library( "//score/launch_manager/daemon/src/alive_monitor/details/timers:time_conversion", "//score/launch_manager/daemon/src/alive_monitor/details/timers:timers_os_clock", "//score/launch_manager/daemon/src/common:identifier_hash", - "@flatbuffers", + "//score/launch_manager/daemon/src/configuration:config", ] + select({ "@platforms//os:qnx": [], "@platforms//os:linux": ["//externals/acl"], diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp index 49975481e..594acfd31 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp @@ -15,7 +15,6 @@ #include #include -#include #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/alive_monitor/details/factory/IPhmFactory.hpp" @@ -40,59 +39,27 @@ namespace factory namespace { -/// @brief Prefix for all log messages -// coverity[autosar_cpp14_a2_10_4_violation:FALSE] Empty namespace ensures uniqueness for cpp file scope static constexpr const char* kLogPrefix{"Factory for FlatCfg AR24-11:"}; -std::unique_ptr read_flatbuffer_file(const std::string& f_filename_r) +bool isSupervisedType(score::mw::launch_manager::configuration::ApplicationType app_type) { - const std::string configFilePath = std::string("etc/") + f_filename_r.c_str(); - - std::ifstream infile; - infile.open(configFilePath, std::ios::binary | std::ios::in); - if (!infile.is_open()) - { - return nullptr; - } - infile.seekg(0, std::ios::end); - const auto length = static_cast(infile.tellg()); - infile.seekg(0, std::ios::beg); - auto data = std::make_unique(length); - infile.read(data.get(), length); - infile.close(); - return data; + return app_type == score::mw::launch_manager::configuration::ApplicationType::ReportingAndSupervised || + app_type == score::mw::launch_manager::configuration::ApplicationType::StateManager; } } // namespace -/* RULECHECKER_comment(0, 7, check_incomplete_data_member_construction, "Members processDataBase is not \ -required to be initialized using member initializer list.", true_no_defect) */ FlatCfgFactory::FlatCfgFactory(const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) : IPhmFactory(), bufferConfig_r(f_bufferConfig_r), - flatBuffer_p(nullptr), - // loadBuffer_p(nullptr), + config_(nullptr), logger_r(logging::PhmLogger::getLogger(logging::PhmLogger::EContext::factory)) { - static_cast(flatBuffer_p); } -bool FlatCfgFactory::init(const std::string& f_filename_r) +bool FlatCfgFactory::init(const score::mw::launch_manager::configuration::Config& config) { - loadBuffer_p = read_flatbuffer_file(f_filename_r); - if (!loadBuffer_p) - { - logger_r.LogError() << kLogPrefix << "Could not open config file."; - return false; - } - - // parse flatbuffer file - flatBuffer_p = HMFlatBuffer::GetHMEcuCfg(loadBuffer_p.get()); - if (flatBuffer_p == nullptr) - { - logger_r.LogError() << kLogPrefix << "Reading HealthMonitor configuration from FlatCfg failed."; - return false; - } + config_ = &config; return true; } @@ -101,62 +68,42 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro { bool isSuccess{true}; - if (flatBuffer_p->process() != nullptr) + try { - try + supervised_components_.clear(); + for (const auto& comp : config_->components()) { - f_processStates_r.reserve(static_cast(flatBuffer_p->process()->size())); - for (const auto process_p : *flatBuffer_p->process()) + if (isSupervisedType(comp.component_properties.application_profile.application_type)) { - // Construct Process States - ifexm::ProcessCfg processCfg{}; - const auto* shortName = process_p->shortName(); - const char* shortNameStr = shortName->c_str(); - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl Process.shortName MANDATORY - // coverity[dereference] PHM.ecucfgdsl Process.shortName MANDATORY - const std::size_t shortNameLen = shortName->size(); - processCfg.processShortName = std::string_view(shortNameStr, shortNameLen); - - // Not an EXM Process - if (process_p->processType() != HMFlatBuffer::ProcessType::ProcessType_LM_PROCESS) - { - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl Process.identifier MANDATORY - // coverity[dereference] PHM.ecucfgdsl Process.identifier MANDATORY - const std::string processPath{process_p->identifier()->c_str()}; - - const auto processIdResult_p{getProcessId(processPath)}; - processCfg.processId = *processIdResult_p; - - f_processStates_r.emplace_back(processCfg); - isSuccess = - f_processStateReader_r.registerProcessState(f_processStates_r.back(), processCfg.processId); - if (!isSuccess) - { - break; - } - } - else - { - // EXM processId - processCfg.processId = -2; - - f_processStates_r.emplace_back(processCfg); - } - - const std::string processShortNameRead{f_processStates_r.back().getConfigName()}; - logger_r.LogDebug() << kLogPrefix << "Successfully created Process States:" << processShortNameRead; + supervised_components_.push_back(&comp); } } - catch (const std::exception& f_exception_r) + + f_processStates_r.reserve(supervised_components_.size()); + for (const auto* comp : supervised_components_) { - isSuccess = false; - logger_r.LogError() << kLogPrefix << "Could not create Process States due to exception:" - << std::string_view{f_exception_r.what()}; + ifexm::ProcessCfg processCfg{}; + processCfg.processShortName = std::string_view(comp->name); + + const auto processIdResult_p{getProcessId(comp->name)}; + processCfg.processId = *processIdResult_p; + + f_processStates_r.emplace_back(processCfg); + isSuccess = + f_processStateReader_r.registerProcessState(f_processStates_r.back(), processCfg.processId); + if (!isSuccess) + { + break; + } + + logger_r.LogDebug() << kLogPrefix << "Successfully created Process States:" << comp->name; } } - else + catch (const std::exception& f_exception_r) { isSuccess = false; + logger_r.LogError() << kLogPrefix << "Could not create Process States due to exception:" + << std::string_view{f_exception_r.what()}; } if (isSuccess) @@ -166,7 +113,6 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro } else { - // Deregister all constructed process states for (auto& processState_r : f_processStates_r) { f_processStateReader_r.deregisterProcessState(processState_r.getProcessId()); @@ -182,16 +128,12 @@ bool FlatCfgFactory::initIpcServerWithUidBasedAccess(ifappl::CheckpointIpcServer const std::string& f_ipcPath_r, const std::int32_t f_uid) noexcept(false) { - // PHM Daemon needs to read from IPC and set ACL permissions (owner: r/w access) - // Application needs to open the IPC channel and write to it (r/w access set via ACL for specific uid, group: no - // access) constexpr mode_t kOwnerReadWrite{384U}; // 0600 in octal if (f_ipcServer_r.init(f_ipcPath_r, kOwnerReadWrite) != ifappl::CheckpointIpcServer::EIpcInitResult::kOk) { return false; } - /// The allowed range of 0-65533 can be safely casted to uid_t (uint32_t on linux and int32_t on qnx) const uid_t uid = static_cast(f_uid); if (!f_ipcServer_r.setAccessRights(uid)) { @@ -205,45 +147,35 @@ bool FlatCfgFactory::initIpcServerWithUidBasedAccess(ifappl::CheckpointIpcServer bool FlatCfgFactory::createMonitorIfIpcs(std::vector& f_interfaceIpcs_r) { bool isSuccess{true}; - if (flatBuffer_p->hmMonitorInterface() != nullptr) + try { - try + f_interfaceIpcs_r.reserve(supervised_components_.size()); + + for (const auto* comp : supervised_components_) { - f_interfaceIpcs_r.reserve(static_cast(flatBuffer_p->hmMonitorInterface()->size())); + const std::string pathInterface = "lifecycle_health_" + comp->name; + f_interfaceIpcs_r.emplace_back(); + const std::int32_t configuredUid = static_cast(comp->deployment_config.sandbox.uid); + isSuccess = initIpcServerWithUidBasedAccess(f_interfaceIpcs_r.back(), pathInterface, configuredUid); - for (auto hmMonitorInterface_p : *flatBuffer_p->hmMonitorInterface()) + if (isSuccess) { - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl PhmMonitorInterface.interfacePath MANDATORY - // coverity[dereference] PHM.ecucfgdsl PhmMonitorInterface.interfacePath MANDATORY - const std::string pathInterface{hmMonitorInterface_p->interfacePath()->c_str()}; - f_interfaceIpcs_r.emplace_back(); - const std::int32_t configuredUid{hmMonitorInterface_p->permittedUid()}; - isSuccess = initIpcServerWithUidBasedAccess(f_interfaceIpcs_r.back(), pathInterface, configuredUid); - - if (isSuccess) - { - logger_r.LogDebug() << kLogPrefix - << "Successfully created Monitor interface IPC with path:" << pathInterface; - } - else - { - logger_r.LogError() << kLogPrefix - << "Could not create Monitor interface IPC with path:" << pathInterface; - break; - } + logger_r.LogDebug() << kLogPrefix + << "Successfully created Monitor interface IPC with path:" << pathInterface; + } + else + { + logger_r.LogError() << kLogPrefix + << "Could not create Monitor interface IPC with path:" << pathInterface; + break; } - } - catch (const std::exception& f_exception_r) - { - isSuccess = false; - logger_r.LogError() << kLogPrefix << "Could not create Monitor interface IPC due to exception:" - << std::string_view{f_exception_r.what()}; } } - else + catch (const std::exception& f_exception_r) { isSuccess = false; - logger_r.LogError() << kLogPrefix << "Could not create Monitor interface IPCs due to missing configuration"; + logger_r.LogError() << kLogPrefix << "Could not create Monitor interface IPC due to exception:" + << std::string_view{f_exception_r.what()}; } if (isSuccess) @@ -272,18 +204,10 @@ bool FlatCfgFactory::createMonitorIf(std::vector& f_int for (auto& interfaceIpc : f_interfaceIpcs_r) { f_interfaces_r.emplace_back(interfaceIpc, interfaceIpc.getPath().data()); - - // Shared Memories (f_interfaceIpcs_r) has also been created from PhmMonitorInterface config - // Accessing the same index (vector <-> config vector) is mapping the same configuration. - // coverity[cert_exp34_c_violation] f_interfaceIpcs_r is created from PhmMonitorInterface - // coverity[dereference] f_interfaceIpcs_r is created from PhmMonitorInterface same size assured - auto refProcessIndex{flatBuffer_p->hmMonitorInterface()->Get(index)->refProcessIndex()}; - - f_processStates_r.at(static_cast(refProcessIndex)).attachObserver(f_interfaces_r.back()); + f_processStates_r.at(static_cast(index)).attachObserver(f_interfaces_r.back()); logger_r.LogDebug() << kLogPrefix << "Successfully created MonitorInterface:" << f_interfaces_r.back().getInterfaceName(); - // coverity[autosar_cpp14_a4_7_1_violation] Value limited by amount of interfaces, which is smaller. index++; } @@ -307,44 +231,29 @@ bool FlatCfgFactory::createSupervisionCheckpoints(std::vectorhmSupervisionCheckpoint() != nullptr) + try { - auto numberOfCheckpoints{flatBuffer_p->hmSupervisionCheckpoint()->size()}; - try - { - f_checkpoints_r.reserve(static_cast(numberOfCheckpoints)); + f_checkpoints_r.reserve(supervised_components_.size()); - for (auto hmSupervisionCheckpoint_p : *flatBuffer_p->hmSupervisionCheckpoint()) - { - const char* const checkpointCfgName{hmSupervisionCheckpoint_p->shortName()->c_str()}; - const uint32_t checkpointId{hmSupervisionCheckpoint_p->checkpointId()}; - const uint32_t refInterfaceIndex{hmSupervisionCheckpoint_p->refInterfaceIndex()}; - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl ensures valid link btw. PhmSupervisionCheckpoint and - // PhmMonitorInterface coverity[dereference] PHM.ecucfgdsl ensures valid link btw. - // PhmSupervisionCheckpoint and PhmMonitorInterface - const auto refProcessIndex{ - flatBuffer_p->hmMonitorInterface()->Get(refInterfaceIndex)->refProcessIndex()}; - const ifexm::ProcessState* process_p{&f_processStates_r.at(static_cast(refProcessIndex))}; - - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl PhmSupervisionCheckpoint.shortName is MANDATORY - // coverity[dereference] PHM.ecucfgdsl PhmSupervisionCheckpoint.shortName is MANDATORY - f_checkpoints_r.emplace_back(checkpointCfgName, checkpointId, process_p); - f_interfaces_r.at(refInterfaceIndex).attachCheckpoint(f_checkpoints_r.back()); - - logger_r.LogDebug() << kLogPrefix << "Successfully created supervision checkpoint:" - << f_checkpoints_r.back().getConfigName(); - } - } - catch (const std::exception& f_exception_r) + for (size_t idx = 0; idx < supervised_components_.size(); ++idx) { - isSuccess = false; - logger_r.LogError() << kLogPrefix << "Could not create supervision worker objects, due to exception:" - << std::string_view{f_exception_r.what()}; + const auto* comp = supervised_components_[idx]; + const std::string checkpointCfgName = comp->name + "_checkpoint"; + const uint32_t checkpointId = 1U; + + const ifexm::ProcessState* process_p{&f_processStates_r.at(idx)}; + f_checkpoints_r.emplace_back(checkpointCfgName.c_str(), checkpointId, process_p); + f_interfaces_r.at(idx).attachCheckpoint(f_checkpoints_r.back()); + + logger_r.LogDebug() << kLogPrefix << "Successfully created supervision checkpoint:" + << f_checkpoints_r.back().getConfigName(); } } - else + catch (const std::exception& f_exception_r) { isSuccess = false; + logger_r.LogError() << kLogPrefix << "Could not create supervision worker objects, due to exception:" + << std::string_view{f_exception_r.what()}; } if (isSuccess) @@ -368,66 +277,58 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ { bool isSuccess{true}; - // If HmAliveSupervision is not configured in configuration files, nullptr is returned by HmAliveSupervision(). - // It is valid to have empty (zero) HmAliveSupervision in the configuration. - if (flatBuffer_p->hmAliveSupervision() != nullptr) + try { - auto numberOfAliveSup{flatBuffer_p->hmAliveSupervision()->size()}; - try - { - f_alive_r.reserve(static_cast(numberOfAliveSup)); + f_alive_r.reserve(supervised_components_.size()); - for (auto hmAliveSupervision_p : *flatBuffer_p->hmAliveSupervision()) + for (size_t idx = 0; idx < supervised_components_.size(); ++idx) + { + const auto* comp = supervised_components_[idx]; + const auto& alive_sup = comp->component_properties.application_profile.alive_supervision; + if (!alive_sup.has_value()) { - // Collect Alive Supervision configuration - const char* nameCfgAlive_p{hmAliveSupervision_p->ruleContextKey()->c_str()}; - saf::timers::NanoSecondType aliveReferenceCycleCfg{ - timers::TimeConversion::convertMilliSecToNanoSec(hmAliveSupervision_p->aliveReferenceCycle())}; - uint32_t minAliveIndicationsCfg{hmAliveSupervision_p->minAliveIndications()}; - uint32_t maxAliveIndicationsCfg{hmAliveSupervision_p->maxAliveIndications()}; - bool isMinCheckDisabledCfg{hmAliveSupervision_p->isMinCheckDisabled()}; - bool isMaxCheckDisabledCfg{hmAliveSupervision_p->isMaxCheckDisabled()}; - uint32_t failedCyclesToleranceCfg{hmAliveSupervision_p->failedSupervisionCyclesTolerance()}; - uint32_t refCheckPointIndexTemp{hmAliveSupervision_p->refCheckPointIndex()}; - - const auto processIndex{hmAliveSupervision_p->refProcessIndex()}; - - // Construct Alive Supervision - supervision::AliveSupervisionCfg aliveSupCfg{ - f_checkpoints_r.at(static_cast(refCheckPointIndexTemp))}; - - aliveSupCfg.cfgName_p = nameCfgAlive_p; - aliveSupCfg.aliveReferenceCycle = aliveReferenceCycleCfg; - aliveSupCfg.minAliveIndications = minAliveIndicationsCfg; - aliveSupCfg.maxAliveIndications = maxAliveIndicationsCfg; - aliveSupCfg.isMinCheckDisabled = isMinCheckDisabledCfg; - aliveSupCfg.isMaxCheckDisabled = isMaxCheckDisabledCfg; - aliveSupCfg.failedCyclesTolerance = failedCyclesToleranceCfg; - aliveSupCfg.checkpointBufferSize = bufferConfig_r.bufferSizeAliveSupervision; - aliveSupCfg.recoveryClient = f_recoveryClient_r; - - // coverity[cert_exp34_c_violation] PHM.ecucfgdsl Process.identifier MANDATORY - // coverity[dereference] PHM.ecucfgdsl Process.identifier MANDATORY - aliveSupCfg.processIdentifier = - score::lcm::IdentifierHash{flatBuffer_p->process()->Get(processIndex)->identifier()->str()}; - - f_alive_r.emplace_back(aliveSupCfg); - - // Subscribe created Alive Supervision to ProcessState class - f_processStates_r.at(static_cast(processIndex)).attachObserver(f_alive_r.back()); - - logger_r.LogDebug() << kLogPrefix << "Successfully created alive supervision worker object:" - << f_alive_r.back().getConfigName(); + continue; } + + const std::string nameCfgAlive = comp->name + "_alive_supervision"; + saf::timers::NanoSecondType aliveReferenceCycleCfg{ + timers::TimeConversion::convertMilliSecToNanoSec(static_cast(alive_sup->reporting_cycle_ms))}; + uint32_t minAliveIndicationsCfg = alive_sup->min_indications.value_or(0U); + uint32_t maxAliveIndicationsCfg = alive_sup->max_indications.value_or(0U); + bool isMinCheckDisabledCfg = (minAliveIndicationsCfg == 0U); + bool isMaxCheckDisabledCfg = (maxAliveIndicationsCfg == 0U); + uint32_t failedCyclesToleranceCfg = alive_sup->failed_cycles_tolerance; + + supervision::AliveSupervisionCfg aliveSupCfg{ + f_checkpoints_r.at(idx)}; + + aliveSupCfg.cfgName_p = nameCfgAlive.c_str(); + aliveSupCfg.aliveReferenceCycle = aliveReferenceCycleCfg; + aliveSupCfg.minAliveIndications = minAliveIndicationsCfg; + aliveSupCfg.maxAliveIndications = maxAliveIndicationsCfg; + aliveSupCfg.isMinCheckDisabled = isMinCheckDisabledCfg; + aliveSupCfg.isMaxCheckDisabled = isMaxCheckDisabledCfg; + aliveSupCfg.failedCyclesTolerance = failedCyclesToleranceCfg; + aliveSupCfg.checkpointBufferSize = bufferConfig_r.bufferSizeAliveSupervision; + aliveSupCfg.recoveryClient = f_recoveryClient_r; + + aliveSupCfg.processIdentifier = score::lcm::IdentifierHash{comp->name}; + + f_alive_r.emplace_back(aliveSupCfg); + + f_processStates_r.at(idx).attachObserver(f_alive_r.back()); + + logger_r.LogDebug() << kLogPrefix << "Successfully created alive supervision worker object:" + << f_alive_r.back().getConfigName(); } - catch (const std::exception& f_exception_r) - { - isSuccess = false; - logger_r.LogError() << kLogPrefix - << "Could not create all necessary alive supervision " - "worker objects, due to exception:" - << std::string_view{f_exception_r.what()}; - } + } + catch (const std::exception& f_exception_r) + { + isSuccess = false; + logger_r.LogError() << kLogPrefix + << "Could not create all necessary alive supervision " + "worker objects, due to exception:" + << std::string_view{f_exception_r.what()}; } if (isSuccess) diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp index f0aee86af..d7594ce1c 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp @@ -23,8 +23,7 @@ #include "score/mw/launch_manager/alive_monitor/details/factory/IPhmFactory.hpp" #include "score/mw/launch_manager/alive_monitor/details/factory/MachineConfigFactory.hpp" #include "score/mw/launch_manager/alive_monitor/details/ifexm/ProcessStateReader.hpp" -#include "score/mw/launch_manager/alive_monitor/config/hm_flatcfg_generated.h" -#include "flatbuffers/flatbuffers.h" +#include "score/mw/launch_manager/configuration/config.hpp" namespace score { namespace lcm { @@ -47,8 +46,8 @@ class PhmLogger; namespace factory { -/// @brief PHM Factory for FlatCfg AR21-11 format -/// @details Provides methods to create worker objects depending on a AR21-11 based PHM FlatCfg file +/// @brief PHM Factory that reads configuration from the unified launch_manager_config.bin +/// @details Provides methods to create worker objects from the new Config type /// and establishes required links between the worker objects automatically. class FlatCfgFactory : public IPhmFactory { @@ -58,8 +57,6 @@ class FlatCfgFactory : public IPhmFactory explicit FlatCfgFactory(const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r); /// @brief Destructor - /* RULECHECKER_comment(0, 5, check_min_instructions, "Default destructor is not provided\ - a function body", true_no_defect) */ ~FlatCfgFactory() override = default; /// @brief No Copy Constructor @@ -71,12 +68,10 @@ class FlatCfgFactory : public IPhmFactory /// @brief No Move Assignment FlatCfgFactory& operator=(FlatCfgFactory&&) = delete; - /// @brief Initialize SW cluster - /// @param [inout] f_flatCfgPhm_r FlatCfg configuration for PHM - /// @param [in] f_nameSwCluster_r Software Cluster name which for which workers shall be constructed - /// @return Initialization is successful (true), otherwise failure (false) - // bool init(flatcfg::FlatCfg& f_flatCfgPhm_r, const std::string& f_nameSwCluster_r); - bool init(const std::string& f_filename_r); + /// @brief Initialize from the unified Config object + /// @param [in] config The parsed launch manager configuration + /// @return true on success + bool init(const score::mw::launch_manager::configuration::Config& config); /// @brief Refer to the description of the base class (IPhmFactory) bool createProcessStates(std::vector& f_processStates_r, @@ -109,11 +104,6 @@ class FlatCfgFactory : public IPhmFactory std::optional getProcessId(const std::string& f_processPath_r) noexcept(true); /// @brief Create IPC Channel with uid-based access permission - /// @details Only the given uid will ge granted r/w access, no group will be granted access - /// @param[in,out] f_ipcServer_r The IPC server object - /// @param[in] f_ipcPath_r The name of the IPC channel - /// @param[in] f_uid The uid that will be assigned r/w permissions for ipc communication - /// @return True if creation was successful, else false bool initIpcServerWithUidBasedAccess(ifappl::CheckpointIpcServer& f_ipcServer_r, const std::string& f_ipcPath_r, const std::int32_t f_uid) noexcept(false); @@ -121,12 +111,11 @@ class FlatCfgFactory : public IPhmFactory /// @brief The buffer configuration for constructing supervision objects const factory::MachineConfigFactory::SupervisionBufferConfig& bufferConfig_r; - /// Pointer to PHM Flat Buffer for given Software Cluster - /// Raw pointer is used here because the memory is deallocated by FlatBuffer. - const HMFlatBuffer::HMEcuCfg* flatBuffer_p; + /// Pointer to the unified configuration (not owned) + const score::mw::launch_manager::configuration::Config* config_; - /// Pointer for loaded Software Cluster - std::unique_ptr loadBuffer_p; + /// Filtered list of supervised components (pointers into config_->components()) + std::vector supervised_components_; /// Logger object for logging messages logging::PhmLogger& logger_r; diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp index a00f3eb0e..a01dd2445 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp @@ -12,12 +12,10 @@ ********************************************************************************/ #include "score/mw/launch_manager/alive_monitor/details/factory/MachineConfigFactory.hpp" +#include #include #include -#include #include "score/mw/launch_manager/alive_monitor/details/timers/TimeConversion.hpp" -#include "score/mw/launch_manager/alive_monitor/config/hmcore_flatcfg_generated.h" -#include "flatbuffers/flatbuffers.h" namespace score @@ -31,136 +29,39 @@ namespace factory namespace { -/// @brief Prefix for all log messages -// coverity[autosar_cpp14_a2_10_4_violation:FALSE] Empty namespace ensures uniqueness for cpp file scope static constexpr char const* kLogPrefix{"Factory for FlatCfg MachineConfig:"}; - -/// @brief Update a field in case the provided value is not the flatbuffer default value -/// @note In case of optional integer values in flatbuffer files, the flatbuffer API will just return 0 if the value was -/// not set. For all optional integers of the machine config, 0 would be invalid so we can safely use this to recognize -/// the default value. -/// @param [in,out] f_field_r The field to update -/// @param [in] f_value The value provided by flatbuffer -void updateNonDefaultValue(std::uint16_t& f_field_r, const std::uint16_t f_value) noexcept(true) -{ - constexpr static std::uint16_t defaultValue{0U}; - if (f_value != defaultValue) - { - f_field_r = f_value; - } -} - -std::unique_ptr read_flatbuffer_file(const std::string& f_filename_r) { - const std::string configFilePath = std::string("etc/") + f_filename_r.c_str(); - - std::ifstream infile; - infile.open(configFilePath, std::ios::binary | std::ios::in); - if (!infile.is_open()) { - return nullptr; - } - infile.seekg(0, std::ios::end); - const auto length = static_cast(infile.tellg()); - infile.seekg(0, std::ios::beg); - auto data = std::make_unique(length); - infile.read(data.get(), length); - infile.close(); - return data; -} } // namespace MachineConfigFactory::MachineConfigFactory() noexcept(true) : watchdog::IDeviceConfigFactory() { } -bool MachineConfigFactory::init() noexcept(false) +bool MachineConfigFactory::init(const score::mw::launch_manager::configuration::Config& config) noexcept(false) { - std::unique_ptr loadBuffer_p = read_flatbuffer_file("hmcore.bin"); - if(!loadBuffer_p) { - logger_r.LogInfo() << kLogPrefix << "No HM Machine Configuration found. Using default configuration."; - logConfiguration(); - return true; + const auto& alive_sup = config.aliveSupervision(); + if (alive_sup.evaluation_cycle_ms != 0U) + { + cycleTimeNs = timers::TimeConversion::convertMilliSecToNanoSec(static_cast(alive_sup.evaluation_cycle_ms)); } - // parse flatbuffer file - flatBuffer_p = HMCOREFlatBuffer::GetHMCOREEcuCfg(loadBuffer_p.get()); - if (flatBuffer_p == nullptr) + const auto& wd_opt = config.watchdog(); + if (wd_opt.has_value()) { - logger_r.LogError() << kLogPrefix << "Reading HM configuration from FlatCfg failed."; - return false; + const auto& wd = *wd_opt; + watchdog::DeviceConfig wdConfig{}; + wdConfig.fileName = wd.device_file_path; + assert(wd.max_timeout_ms <= std::numeric_limits::max()); + wdConfig.timeoutMax = static_cast(wd.max_timeout_ms); + wdConfig.canBeDeactivated = wd.deactivate_on_shutdown; + wdConfig.needsMagicClose = wd.require_magic_close; + watchdogConfigs.push_back(std::move(wdConfig)); } - // No error and found a machine config - return loadHmCoreConfig(flatBuffer_p); -} - -bool MachineConfigFactory::loadHmCoreConfig(const HMCOREFlatBuffer::HMCOREEcuCfg* f_cfg_r) noexcept(false) -{ - loadHmSettings(*f_cfg_r); - loadWatchdogDevices(*f_cfg_r); logger_r.LogInfo() << kLogPrefix << "Loading of HM Machine Configuration succeeded."; logConfiguration(); return true; } -void MachineConfigFactory::loadWatchdogDevices(const HMCOREFlatBuffer::HMCOREEcuCfg& f_flatBuffer_r) noexcept(false) -{ - const auto* watchdogs{f_flatBuffer_r.watchdogs()}; - if ((watchdogs == nullptr) || (watchdogs->size() == 0U)) - { - // no watchdog devices configured - return; - } - - watchdogConfigs.reserve(static_cast(watchdogs->size())); - for (const auto& wdg : *watchdogs) - { - watchdog::DeviceConfig config{}; - - assert(wdg->maxTimeout() <= std::numeric_limits::max()); - // coverity[autosar_cpp14_a4_7_1_violation] SDG definitions guarantee uint16 boundaries - config.timeoutMax = static_cast(wdg->maxTimeout()); - - // coverity[cert_exp34_c_violation] HMCORE.ecucfgdsl Watchdog.deviceFilePath MANDATORY - // coverity[dereference] HMCORE.ecucfgdsl Watchdog.deviceFilePath MANDATORY - config.fileName = wdg->deviceFilePath()->str(); - if (wdg->hasValueDeactivateOnShutdown()) - { - config.canBeDeactivated = wdg->deactivateOnShutdown(); - } - if (wdg->hasValueRequireMagicClose()) - { - config.needsMagicClose = wdg->requireMagicClose(); - } - watchdogConfigs.push_back(std::move(config)); - } -} - -void MachineConfigFactory::loadHmSettings(const HMCOREFlatBuffer::HMCOREEcuCfg& f_flatBuffer_r) noexcept(true) -{ - const auto* configContainer{f_flatBuffer_r.config()}; - if ((configContainer != nullptr) && (configContainer->size() == 1U)) - { - const auto* config{configContainer->Get(0U)}; - updateNonDefaultValue(supBufferCfg.bufferSizeAliveSupervision, config->bufferSizeAliveSupervision()); - updateNonDefaultValue(supBufferCfg.bufferSizeMonitor, config->bufferSizeMonitor()); - if (config->periodicity() != 0U) - { - cycleTimeNs = timers::TimeConversion::convertMilliSecToNanoSec(static_cast(config->periodicity())); - } - - // Because the hm-lib will also need to know of a changed shared memory size (which it currently does not). - // The support for configuring shared memory size is delayed until pipc migration. - if (supBufferCfg.bufferSizeMonitor != StaticConfig::k_DefaultMonitorBufferElements) - { - supBufferCfg.bufferSizeMonitor = StaticConfig::k_DefaultMonitorBufferElements; - logger_r.LogWarn() << kLogPrefix - << "Configuring Supervised Entity buffer size from machine config is currently not " - "supported. Using default buffer size of" - << StaticConfig::k_DefaultMonitorBufferElements << "checkpoints"; - } - } -} - std::optional MachineConfigFactory::getDeviceConfigurations() const { @@ -180,7 +81,6 @@ const MachineConfigFactory::SupervisionBufferConfig& MachineConfigFactory::getSu void MachineConfigFactory::logConfiguration() noexcept(true) { - /* RULECHECKER_comment(0, 18, check_conditional_as_sub_expression, "Ternary operation is very simple", true_no_defect) */ logger_r.LogDebug() << kLogPrefix << "Alive Supervision buffer size:" << supBufferCfg.bufferSizeAliveSupervision; logger_r.LogDebug() << kLogPrefix << "Monitor buffer size:" << supBufferCfg.bufferSizeMonitor; logger_r.LogDebug() << kLogPrefix << "Periodicity:" << getCycleTimeInNs() << "ns"; @@ -195,7 +95,6 @@ void MachineConfigFactory::logConfiguration() noexcept(true) logger_r.LogDebug() << kLogPrefix << "Watchdog" << wdgCount << "- needs magic close:" << wdgMagicCloseBool; logger_r.LogDebug() << kLogPrefix << "Watchdog" << wdgCount << "- deactivate on hm shutdown:" << wdgDeactivatedBool; - // coverity[autosar_cpp14_a4_7_1_violation] Value limited by amount of watchdog configurations, which is smaller. ++wdgCount; } diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp index ab4d7b071..21c0384dd 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp @@ -20,12 +20,7 @@ #include "score/mw/launch_manager/alive_monitor/details/logging/PhmLogger.hpp" #include "score/mw/launch_manager/alive_monitor/details/timers/Timers_OsClock.hpp" #include "score/mw/launch_manager/alive_monitor/details/watchdog/IDeviceConfigFactory.hpp" - -namespace HMCOREFlatBuffer -{ -/* RULECHECKER_comment(1:0,1:0, check_non_pod_struct, "External data type form generated flatbuffer code", true_no_defect) */ -struct HMCOREEcuCfg; -} // namespace PHMCOREFlatBuffer +#include "score/mw/launch_manager/configuration/config.hpp" namespace score { @@ -42,14 +37,11 @@ class PhmLogger; namespace factory { -/// @brief Factory for loading the HM Machine Configuration -/// @details Provides methods to retrieve the settings from the HM Machine configuration if a configuration is -/// provided. If no configuration is provided, the default values are returned. +/// @brief Factory for loading the HM Machine Configuration from the unified launch_manager_config.bin class MachineConfigFactory : public watchdog::IDeviceConfigFactory { public: /// @brief Holds different buffer sizes that may be configured in the HM Machine Config - /// @details All buffer sizes are initialized with their default value struct SupervisionBufferConfig { /// @brief Configured buffer size for alive supervisions @@ -73,44 +65,23 @@ class MachineConfigFactory : public watchdog::IDeviceConfigFactory /// @brief No Move Assignment MachineConfigFactory& operator=(MachineConfigFactory&&) = delete; - /// @brief Load and parse machine configuration - /// @return True, if either no machine configuration is provided or a valid configuration was successfully loaded. - /// False, if an invalid machine configuration was provided. - /// @note FlatCfg constructor does not define any exception guarantee and may throw a non specified exception - /// @throws std::bad_alloc in case of insufficient memory - bool init() noexcept(false); + /// @brief Load machine configuration from the unified Config object + bool init(const score::mw::launch_manager::configuration::Config& config) noexcept(false); /// @copydoc IDeviceConfigFactory::getDeviceConfigurations() std::optional getDeviceConfigurations() const override; /// @brief Returns the configured hm daemon cycle time in nanoseconds - /// @return Configured cycle time or default cycle time if not configured timers::NanoSecondType getCycleTimeInNs() const noexcept(true); /// @brief Returns the configured buffer sizes for supervisions - /// @return Configured buffer sizes or default values if not configured const SupervisionBufferConfig& getSupervisionBufferConfig() const noexcept(true); private: - /// @brief Loads the hm machine config - /// @param [in] f_cfg_r The flatcfg api - /// @throws std::bad_alloc for string allocation in case of insufficient memory - /// @return true if no error occurred, else false - bool loadHmCoreConfig(const HMCOREFlatBuffer::HMCOREEcuCfg* f_cfg_r) noexcept(false); - - /// @brief Loads the watchdog device configuration from machine config - /// @param [in] f_flatBuffer_r The loaded machine config - void loadWatchdogDevices(const HMCOREFlatBuffer::HMCOREEcuCfg& f_flatBuffer_r) noexcept(false); - - /// @brief Load HM settings from the machine config. I.e. buffer sizes, periodicity, etc. - /// @param [in] f_flatBuffer_r The flatcfg buffer - void loadHmSettings(const HMCOREFlatBuffer::HMCOREEcuCfg& f_flatBuffer_r) noexcept(true); - /// @brief Log all configuration settings void logConfiguration() noexcept(true); /// @brief Configured watchdog devices - /// By default, no watchdog device is configured watchdog::IDeviceConfigFactory::DeviceConfigurations watchdogConfigs{}; /// @brief Configured HM Daemon cycle time @@ -119,10 +90,6 @@ class MachineConfigFactory : public watchdog::IDeviceConfigFactory /// @brief Configured supervision buffer sizes SupervisionBufferConfig supBufferCfg{}; - /// Pointer to HM Flat Buffer for given Software Cluster - /// Raw pointer is used here because the memory is deallocated by FlatBuffer. - const HMCOREFlatBuffer::HMCOREEcuCfg* flatBuffer_p; - /// Logger object for logging messages logging::PhmLogger& logger_r{logging::PhmLogger::getLogger(logging::PhmLogger::EContext::factory)}; }; diff --git a/score/launch_manager/daemon/src/configuration/BUILD b/score/launch_manager/daemon/src/configuration/BUILD index 5fd650671..6c0174a83 100644 --- a/score/launch_manager/daemon/src/configuration/BUILD +++ b/score/launch_manager/daemon/src/configuration/BUILD @@ -134,15 +134,16 @@ cc_library( ) cc_library( - name = "configuration_manager", - srcs = ["configuration_manager.cpp"], - hdrs = ["configuration_manager.hpp"], + name = "configuration_adapter", + srcs = ["configuration_adapter.cpp"], + hdrs = ["configuration_adapter.hpp"], include_prefix = "score/mw/launch_manager/configuration", strip_include_prefix = "/score/launch_manager/daemon/src/configuration", visibility = ["//score:__subpackages__"], deps = [ - ":lm_flatcfg", - "//score/launch_manager:error", + ":config", + ":config_loader", + ":flatbuffer_config_loader", "//score/launch_manager/daemon/src/common:constants", "//score/launch_manager/daemon/src/common:identifier_hash", "//score/launch_manager/daemon/src/common:log", @@ -150,6 +151,5 @@ cc_library( "//score/launch_manager/daemon/src/osal:num_cores", "//score/launch_manager/daemon/src/process_group_manager:iprocess", "//score/launch_manager/daemon/src/process_state_client:posix_process", - "@flatbuffers", ], ) diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp new file mode 100644 index 000000000..644fe3a3f --- /dev/null +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp @@ -0,0 +1,421 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#include "score/mw/launch_manager/configuration/configuration_adapter.hpp" +#include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" +#include "score/mw/launch_manager/common/log.hpp" +#include "score/mw/launch_manager/osal/num_cores.hpp" + +#include +#include +#include +#include +#include + +namespace score::mw::launch_manager::configuration { + +const uint32_t ConfigurationAdapter::kDefaultProcessExecutionError = 1U; +uint32_t ConfigurationAdapter::kDefaultProcessorAffinityMask() { + return static_cast((1ULL << score::lcm::internal::osal::getNumCores()) - 1ULL); +} +const int32_t ConfigurationAdapter::kDefaultSchedulingPolicy = SCHED_OTHER; +const int32_t ConfigurationAdapter::kDefaultRealtimeSchedulingPriority = 99; +const int32_t ConfigurationAdapter::kDefaultNormalSchedulingPriority = 0; + +score::lcm::internal::osal::CommsType ConfigurationAdapter::mapApplicationType( + ApplicationType app_type) const { + switch (app_type) { + case ApplicationType::Reporting: + case ApplicationType::ReportingAndSupervised: + return score::lcm::internal::osal::CommsType::kReporting; + case ApplicationType::StateManager: + return score::lcm::internal::osal::CommsType::kControlClient; + case ApplicationType::Native: + default: + return score::lcm::internal::osal::CommsType::kNoComms; + } +} + +bool ConfigurationAdapter::initialize() { + LM_LOG_DEBUG() << "Loading LCM Configurations..."; + + const char* env_val = getenv("ECUCFG_ENV_VAR_ROOTFOLDER"); + if (!env_val || strlen(env_val) == 0) { + setenv("ECUCFG_ENV_VAR_ROOTFOLDER", "/opt/internal/launch_manager/etc/ecu-cfg", 1); + } + LM_LOG_DEBUG() << "ECUCFG_ENV_VAR_ROOTFOLDER set successfully"; + + FlatbufferConfigLoader loader; + auto result = loader.load("etc/launch_manager_config.bin"); + if (!result.has_value()) { + LM_LOG_ERROR() << "Failed to load launch_manager_config.bin"; + return false; + } + + return buildFromConfig(std::move(*result)); +} + +void ConfigurationAdapter::deinitialize() { + for (auto& process_group : process_groups_) { + for (auto& process : process_group.processes_) { + for (size_t i = 0U; + i < score::lcm::internal::kArgvArraySize && process.startup_config_.argv_[i] != nullptr; + ++i) { + free(const_cast(process.startup_config_.argv_[i])); + process.startup_config_.argv_[i] = nullptr; + } + for (size_t i = 0U; process.startup_config_.envp_[i] != nullptr; ++i) { + free(process.startup_config_.envp_[i]); + process.startup_config_.envp_[i] = nullptr; + } + } + } +} + +bool ConfigurationAdapter::buildFromConfig(Config config) { + const std::string initial_run_target_name = std::string(config.initialRunTarget()); + + ProcessGroup pg; + const IdentifierHash pg_name{"MainPG"}; + pg.name_ = pg_name; + pg.sw_cluster_ = IdentifierHash{"DefaultSoftwareCluster"}; + pg.off_state_ = IdentifierHash{"MainPG/Off"}; + + const auto& fallback = config.fallbackRunTarget(); + const auto& run_targets = config.runTargets(); + + IdentifierHash recovery_state{"Recovery"}; + for (const auto& rt : run_targets) { + if (rt.recovery_action.run_target == "fallback_run_target") { + recovery_state = IdentifierHash{std::string("MainPG/") + "fallback_run_target"}; + break; + } + } + pg.recovery_state_ = recovery_state; + + std::map component_to_process_index; + uint32_t process_index = 0; + + for (const auto& comp : config.components()) { + OsProcess os_process{}; + os_process.process_id_ = IdentifierHash{comp.name}; + os_process.process_number_ = process_index; + + auto& startup = os_process.startup_config_; + const auto& deploy = comp.deployment_config; + const auto& props = comp.component_properties; + + std::string exec_path = deploy.bin_dir; + if (!exec_path.empty() && exec_path.back() != '/') { + exec_path += '/'; + } + exec_path += props.binary_name; + startup.executable_path_ = exec_path; + startup.short_name_ = comp.name; + + startup.uid_ = deploy.sandbox.uid; + startup.gid_ = deploy.sandbox.gid; + startup.supplementary_gids_ = deploy.sandbox.supplementary_group_ids; + startup.security_policy_ = deploy.sandbox.security_policy.value_or(""); + startup.scheduling_policy_ = deploy.sandbox.scheduling_policy; + startup.scheduling_priority_ = deploy.sandbox.scheduling_priority; + startup.cpu_mask_ = kDefaultProcessorAffinityMask(); + + startup.resource_limits_.stack_ = 0U; + startup.resource_limits_.cpu_ = 0U; + startup.resource_limits_.data_ = 0U; + startup.resource_limits_.as_ = 0U; + if (deploy.sandbox.max_memory_usage.has_value()) { + startup.resource_limits_.as_ = *deploy.sandbox.max_memory_usage; + } + + startup.comms_type_ = mapApplicationType(props.application_profile.application_type); + + size_t arg_index = 0U; + startup.argv_[arg_index] = strdup(startup.executable_path_.c_str()); + ++arg_index; + size_t max_args = std::min(props.process_arguments.size(), + static_cast(score::lcm::internal::kMaxArg)); + for (size_t i = 0U; i < max_args; ++i) { + startup.argv_[arg_index++] = strdup(props.process_arguments[i].c_str()); + } + + size_t env_index = 0U; + size_t max_env = std::min(deploy.environmental_variables.size(), + static_cast(score::lcm::internal::kMaxEnv)); + size_t env_count = 0; + for (const auto& ev : deploy.environmental_variables) { + if (env_count >= max_env) break; + std::string env_str = std::string(ev.key()) + "=" + std::string(ev.value()); + startup.envp_[env_index++] = strdup(env_str.c_str()); + ++env_count; + } + + bool is_sup = (props.application_profile.application_type == ApplicationType::ReportingAndSupervised || + props.application_profile.application_type == ApplicationType::StateManager); + if (is_sup && env_index < static_cast(score::lcm::internal::kMaxEnv)) { + std::string iface_path = "LCM_ALIVE_INTERFACE_PATH=/lifecycle_health_" + comp.name; + startup.envp_[env_index++] = strdup(iface_path.c_str()); + } + + startup.envp_[env_index] = nullptr; + + auto& pgm = os_process.pgm_config_; + pgm.is_self_terminating_ = props.application_profile.is_self_terminating; + pgm.startup_timeout_ms_ = std::chrono::milliseconds(deploy.ready_timeout_ms); + pgm.termination_timeout_ms_ = std::chrono::milliseconds(deploy.shutdown_timeout_ms); + pgm.execution_error_code_ = kDefaultProcessExecutionError; + pgm.number_of_restart_attempts = 0U; + if (deploy.ready_recovery_action.has_value()) { + pgm.number_of_restart_attempts = deploy.ready_recovery_action->number_of_attempts; + } + + for (const auto& dep_name : props.depends_on) { + Dependency dep{}; + if (props.ready_condition.has_value()) { + dep.process_state_ = (props.ready_condition->process_state == ProcessState::Running) + ? score::lcm::ProcessState::kRunning + : score::lcm::ProcessState::kTerminated; + } else { + dep.process_state_ = score::lcm::ProcessState::kRunning; + } + dep.target_process_id_ = IdentifierHash{dep_name}; + os_process.dependencies_.push_back(dep); + } + + component_to_process_index[comp.name] = process_index; + pg.processes_.push_back(std::move(os_process)); + ++process_index; + } + + { + ProcessGroupState off_state; + off_state.name_ = IdentifierHash{"MainPG/Off"}; + pg.states_.push_back(off_state); + } + + std::map run_target_by_name; + for (const auto& rt : run_targets) { + run_target_by_name[rt.name] = &rt; + } + + std::map component_by_name; + for (const auto& comp : config.components()) { + component_by_name[comp.name] = ∁ + } + + std::function&, std::set&)> resolve_depends; + resolve_depends = [&](const std::string& dep_name, + std::vector& indexes, + std::set& visited) { + if (!visited.insert(dep_name).second) return; + auto comp_it = component_to_process_index.find(dep_name); + if (comp_it != component_to_process_index.end()) { + if (std::find(indexes.begin(), indexes.end(), comp_it->second) == indexes.end()) { + indexes.push_back(comp_it->second); + } + auto comp_cfg = component_by_name.find(dep_name); + if (comp_cfg != component_by_name.end()) { + for (const auto& sub_dep : comp_cfg->second->component_properties.depends_on) { + resolve_depends(sub_dep, indexes, visited); + } + } + } + auto rt_it = run_target_by_name.find(dep_name); + if (rt_it != run_target_by_name.end()) { + for (const auto& sub_dep : rt_it->second->depends_on) { + resolve_depends(sub_dep, indexes, visited); + } + } + }; + + for (const auto& rt : run_targets) { + ProcessGroupState pgs; + pgs.name_ = IdentifierHash{std::string("MainPG/") + rt.name}; + + std::set visited; + for (const auto& dep_name : rt.depends_on) { + resolve_depends(dep_name, pgs.process_indexes_, visited); + } + pg.states_.push_back(std::move(pgs)); + } + + { + ProcessGroupState fallback_state; + fallback_state.name_ = IdentifierHash{"MainPG/fallback_run_target"}; + for (const auto& comp_name : fallback.depends_on) { + auto it = component_to_process_index.find(comp_name); + if (it != component_to_process_index.end()) { + fallback_state.process_indexes_.push_back(it->second); + } + } + pg.states_.push_back(std::move(fallback_state)); + } + + for (auto& proc : pg.processes_) { + for (auto& dep : proc.dependencies_) { + for (uint32_t idx = 0; idx < pg.processes_.size(); ++idx) { + if (pg.processes_[idx].process_id_ == dep.target_process_id_) { + dep.os_process_index_ = idx; + break; + } + } + } + } + + process_groups_.push_back(std::move(pg)); + process_group_names_.push_back(pg_name); + + main_pg_startup_state_ = score::lcm::internal::ProcessGroupStateID{ + pg_name, + IdentifierHash{std::string("MainPG/") + initial_run_target_name} + }; + + LM_LOG_DEBUG() << "ConfigurationAdapter: Built configuration with " + << process_groups_[0].processes_.size() << " processes and " + << process_groups_[0].states_.size() << " states"; + + return true; +} + +std::optional*> ConfigurationAdapter::getListOfProcessGroups() const { + if (!process_group_names_.empty()) { + return &process_group_names_; + } + return std::nullopt; +} + +std::optional ConfigurationAdapter::getSoftwareCluster(const IdentifierHash& process_group_id) const { + auto pg = getProcessGroupByID(process_group_id); + if (pg) { + return pg->sw_cluster_; + } + return std::nullopt; +} + +std::optional ConfigurationAdapter::getNumberOfOsProcesses(const IdentifierHash& pg_name) const { + auto pg = getProcessGroupByID(pg_name); + if (pg) { + return static_cast(pg->processes_.size()); + } + return std::nullopt; +} + +IdentifierHash ConfigurationAdapter::getNameOfOffState(const IdentifierHash& pg_name) const { + auto pg = getProcessGroupByID(pg_name); + if (pg) { + return pg->off_state_; + } + return IdentifierHash{"Off"}; +} + +IdentifierHash ConfigurationAdapter::getNameOfRecoveryState(const IdentifierHash& pg_name) const { + auto pg = getProcessGroupByID(pg_name); + if (pg) { + return pg->recovery_state_; + } + return IdentifierHash{"Recovery"}; +} + +std::optional ConfigurationAdapter::getMainPGStartupState() const { + auto pg = getProcessGroupByID(main_pg_startup_state_.pg_name_); + if (pg) { + for (const auto& state : pg->states_) { + if (state.name_ == main_pg_startup_state_.pg_state_name_) { + return &main_pg_startup_state_; + } + } + LM_LOG_DEBUG() << "Process group state not found:" << main_pg_startup_state_.pg_state_name_; + } else { + LM_LOG_DEBUG() << "Process group not found:" << main_pg_startup_state_.pg_name_; + } + return std::nullopt; +} + +std::optional*> ConfigurationAdapter::getProcessIndexesList( + const score::lcm::internal::ProcessGroupStateID& pg_state_id) const { + auto state = getProcessGroupStateByID(pg_state_id); + if (state) { + return &state->process_indexes_; + } + LM_LOG_DEBUG() << "Process group state '" << pg_state_id.pg_state_name_ + << "' not found in group '" << pg_state_id.pg_name_ << "'."; + return std::nullopt; +} + +std::optional ConfigurationAdapter::getOsProcessConfiguration( + const IdentifierHash& pg_name, const uint32_t index) const { + if (auto pg = getProcessGroupByNameAndIndex(pg_name, index)) { + return &(*pg)->processes_[index]; + } + LM_LOG_DEBUG() << "Unable to retrieve process configuration for process group" << pg_name + << "with index" << index; + return std::nullopt; +} + +std::optional ConfigurationAdapter::getOsProcessDependencies( + const IdentifierHash& pg_name, const uint32_t index) const { + if (auto pg = getProcessGroupByNameAndIndex(pg_name, index)) { + return &(*pg)->processes_[index].dependencies_; + } + LM_LOG_DEBUG() << "Unable to retrieve process dependencies for process group" << pg_name + << "with index" << index; + return std::nullopt; +} + +ProcessGroup* ConfigurationAdapter::getProcessGroupByID(const IdentifierHash& pg_name) const { + for (const auto& pg : process_groups_) { + if (pg.name_ == pg_name) { + return const_cast(&pg); + } + } + return nullptr; +} + +ProcessGroupState* ConfigurationAdapter::getProcessGroupStateByID(const score::lcm::internal::ProcessGroupStateID& pg_id) const { + ProcessGroup* pg = getProcessGroupByID(pg_id.pg_name_); + if (pg) { + for (auto& state : pg->states_) { + if (state.name_ == pg_id.pg_state_name_) { + return &state; + } + } + } + return nullptr; +} + +ProcessGroupState* ConfigurationAdapter::getProcessGroupStateByID( + ProcessGroup& pg, const IdentifierHash& state_name) const { + for (auto& state : pg.states_) { + if (state.name_ == state_name) { + return &state; + } + } + return nullptr; +} + +std::optional ConfigurationAdapter::getProcessGroupByNameAndIndex( + const IdentifierHash& pg_name, const uint32_t index) const { + auto pg = getProcessGroupByID(pg_name); + if (pg) { + if (index < pg->processes_.size()) { + return pg; + } + LM_LOG_DEBUG() << "Process index" << index << "is out of bounds in process group" << pg_name; + } else { + LM_LOG_DEBUG() << "Process group not found:" << pg_name; + } + return std::nullopt; +} + +} // namespace score::mw::launch_manager::configuration diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp new file mode 100644 index 000000000..ff1347b19 --- /dev/null +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp @@ -0,0 +1,125 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef CONFIGURATIONADAPTER_HPP_INCLUDED +#define CONFIGURATIONADAPTER_HPP_INCLUDED + +#include +#include +#include +#include +#include "score/mw/launch_manager/configuration/config.hpp" +#include "score/mw/launch_manager/configuration/config_loader.hpp" +#include "score/mw/launch_manager/common/identifier_hash.hpp" +#include "score/mw/launch_manager/common/constants.hpp" +#include "score/mw/launch_manager/common/process_group_state_id.hpp" +#include "score/mw/launch_manager/process_group_manager/iprocess.hpp" +#include "score/mw/launch_manager/process_state_client/posix_process.hpp" + +namespace score::mw::launch_manager::configuration { + +using IdentifierHash = score::lcm::IdentifierHash; + +struct PgManagerConfig final { + bool is_self_terminating_; + std::chrono::milliseconds startup_timeout_ms_; + std::chrono::milliseconds termination_timeout_ms_; + uint32_t number_of_restart_attempts; + uint32_t execution_error_code_; +}; + +struct Dependency final { + score::lcm::ProcessState process_state_; + IdentifierHash target_process_id_; + uint32_t os_process_index_; +}; + +using DependencyList = std::vector; + +struct OsProcess final { + IdentifierHash process_id_; + uint32_t process_number_; + score::lcm::internal::osal::OsalConfig startup_config_{}; + PgManagerConfig pgm_config_; + DependencyList dependencies_; +}; + +struct ProcessGroupState final { + IdentifierHash name_; + std::vector process_indexes_; +}; + +struct ProcessGroup final { + IdentifierHash name_; + IdentifierHash sw_cluster_; + IdentifierHash off_state_; + IdentifierHash recovery_state_; + std::vector states_; + std::vector processes_; +}; + +class ConfigurationAdapter final { + public: + bool initialize(); + void deinitialize(); + + std::optional*> getListOfProcessGroups() const; + std::optional getSoftwareCluster(const IdentifierHash& process_group_id) const; + std::optional getNumberOfOsProcesses(const IdentifierHash& pg_name) const; + IdentifierHash getNameOfOffState(const IdentifierHash& pg_name) const; + IdentifierHash getNameOfRecoveryState(const IdentifierHash& pg_name) const; + std::optional getMainPGStartupState() const; + std::optional*> getProcessIndexesList( + const score::lcm::internal::ProcessGroupStateID& process_group_state_id) const; + std::optional getOsProcessConfiguration(const IdentifierHash& pg_name_, + const uint32_t index) const; + std::optional getOsProcessDependencies(const IdentifierHash& process_group_name, + const uint32_t index) const; + + static const uint32_t kDefaultProcessExecutionError; + static uint32_t kDefaultProcessorAffinityMask(); + static const int32_t kDefaultSchedulingPolicy; + static const int32_t kDefaultRealtimeSchedulingPriority; + static const int32_t kDefaultNormalSchedulingPriority; + + private: + bool buildFromConfig(Config config); + + score::lcm::internal::osal::CommsType mapApplicationType(ApplicationType app_type) const; + + ProcessGroup* getProcessGroupByID(const IdentifierHash& pg_name) const; + ProcessGroupState* getProcessGroupStateByID(const score::lcm::internal::ProcessGroupStateID& pg_id) const; + ProcessGroupState* getProcessGroupStateByID(ProcessGroup& pg, const IdentifierHash& state_name) const; + std::optional getProcessGroupByNameAndIndex(const IdentifierHash& pg_name, + const uint32_t index) const; + + std::vector process_groups_{}; + std::vector process_group_names_{}; + score::lcm::internal::ProcessGroupStateID main_pg_startup_state_{static_cast("MainPG"), + static_cast("MainPG/Startup")}; +}; + +} // namespace score::mw::launch_manager::configuration + +// Aliases for backward compatibility with score::lcm::internal consumers +namespace score::lcm::internal { +using ConfigurationAdapter = score::mw::launch_manager::configuration::ConfigurationAdapter; +using OsProcess = score::mw::launch_manager::configuration::OsProcess; +using DependencyList = score::mw::launch_manager::configuration::DependencyList; +using ProcessGroup = score::mw::launch_manager::configuration::ProcessGroup; +using ProcessGroupState = score::mw::launch_manager::configuration::ProcessGroupState; +using PgManagerConfig = score::mw::launch_manager::configuration::PgManagerConfig; +using Dependency = score::mw::launch_manager::configuration::Dependency; +} // namespace score::lcm::internal + +#endif // CONFIGURATIONADAPTER_HPP_INCLUDED diff --git a/score/launch_manager/daemon/src/configuration/configuration_manager.cpp b/score/launch_manager/daemon/src/configuration/configuration_manager.cpp deleted file mode 100644 index 13c51d5d7..000000000 --- a/score/launch_manager/daemon/src/configuration/configuration_manager.cpp +++ /dev/null @@ -1,883 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - -#include -#include "score/mw/lifecycle/execution_error.h" - -#include "score/mw/launch_manager/configuration/configuration_manager.hpp" -#include "score/mw/launch_manager/common/process_group_state_id.hpp" -#include "score/mw/launch_manager/common/log.hpp" -#include "score/mw/launch_manager/osal/num_cores.hpp" - -#include - -using namespace std; -using namespace LMFlatBuffer; - -namespace { - -/// @brief Retrieves the resource limits configuration from the given config -/// node. -bool setResourceLimits(const LMFlatBuffer::ProcessStartupConfig& startup_config_node, - score::lcm::internal::OsProcess& instance) { - // not supported currently - instance.startup_config_.resource_limits_.stack_ = 0U; // don't set the stack limit - instance.startup_config_.resource_limits_.cpu_ = 0U; // no limit for cpu time - instance.startup_config_.resource_limits_.data_ = 0U; // not supported in ar-24-11 - - // we don't need to check the upper limit as this is done in the tooling - - // 0 means not configured - if (startup_config_node.memoryUsage() > 0U) - instance.startup_config_.resource_limits_.as_ = startup_config_node.memoryUsage(); - - return true; - -} - -std::unique_ptr read_flatbuffer_file(const std::string& f_filename_r) { - const std::string configFilePath = std::string("etc/") + f_filename_r.c_str(); - - std::ifstream infile; - infile.open(configFilePath, std::ios::binary | std::ios::in); - if (!infile.is_open()) { - return nullptr; - } - infile.seekg(0, std::ios::end); - const auto length = static_cast(infile.tellg()); - infile.seekg(0, std::ios::beg); - auto data = std::make_unique(length); - infile.read(data.get(), length); - infile.close(); - return data; -} - -} // namespace - -namespace score { - -namespace lcm { - -namespace internal { - -const char* ConfigurationManager::PROCESS_RUNNING_STATE = "Running"; -const char* ConfigurationManager::PROCESS_TERMINATED_STATE = "Terminated"; - -constexpr const char* kEnvVarName = "ECUCFG_ENV_VAR_ROOTFOLDER"; ///< Environment variable name -constexpr const char* kEnvVarDefaultValue = "/opt/internal/launch_manager/etc/ecu-cfg"; ///< Environment variable value - -const uint32_t ConfigurationManager::kDefaultProcessExecutionError = 1U; -uint32_t ConfigurationManager::kDefaultProcessorAffinityMask() { - return static_cast((1ULL << osal::getNumCores()) - 1ULL); -} -const int32_t ConfigurationManager::kDefaultSchedulingPolicy = SCHED_OTHER; -const int32_t ConfigurationManager::kDefaultRealtimeSchedulingPriority = 99; -const int32_t ConfigurationManager::kDefaultNormalSchedulingPriority = 0; - -std::optional ConfigurationManager::getNumberOfOsProcesses(const IdentifierHash& pg_name) const { - std::optional numberOfProcesses = std::nullopt; - auto pg = getProcessGroupByID(pg_name); - - if (pg) { - numberOfProcesses = std::optional(pg->processes_.size()); - } - - return numberOfProcesses; -} - -IdentifierHash ConfigurationManager::getNameOfOffState(const IdentifierHash& pg_name) const { - IdentifierHash nameOfOffState{"Off"}; - auto pg = getProcessGroupByID(pg_name); - if (pg) { - nameOfOffState = pg->off_state_; - } - return nameOfOffState; -} - -IdentifierHash ConfigurationManager::getNameOfRecoveryState(const IdentifierHash& pg_name) const { - IdentifierHash nameOfRecoveryState{"Recovery"}; - auto pg = getProcessGroupByID(pg_name); - if (pg) { - nameOfRecoveryState = pg->recovery_state_; - } - return nameOfRecoveryState; -} - -std::optional ConfigurationManager::getMainPGStartupState() const { - std::optional result = std::nullopt; - - auto pg = getProcessGroupByID(main_pg_startup_state_.pg_name_); - - if (pg) { - auto pg_state = getProcessGroupStateByID(*pg, main_pg_startup_state_.pg_state_name_); - - if (pg_state) { - result = &main_pg_startup_state_; - } else { - LM_LOG_DEBUG() << "Process group state not found:" << main_pg_startup_state_.pg_state_name_; - } - } else { - LM_LOG_DEBUG() << "Process group not found:" << main_pg_startup_state_.pg_name_; - } - - return result; -} - -std::optional*> ConfigurationManager::getListOfProcessGroups() const { - std::optional*> result = std::nullopt; - - if (!process_group_names_.empty()) { - result = &process_group_names_; - } - - return result; -} - -std::optional*> ConfigurationManager::getProcessIndexesList( - const ProcessGroupStateID& pg_state_id) const { - std::optional*> result = std::nullopt; - - auto state = getProcessGroupStateByID(pg_state_id); - - if (state) { - result = &state->process_indexes_; - } else { - LM_LOG_DEBUG() << "Process group state '" << pg_state_id.pg_state_name_ << "' not found in group '" - << pg_state_id.pg_name_ << "'."; - } - - return result; -} - -std::optional ConfigurationManager::getOsProcessConfiguration(const IdentifierHash& pg_name, - const uint32_t index) const { - std::optional result = std::nullopt; - - if (auto pg = getProcessGroupByNameAndIndex(pg_name, index)) { - result = &(*pg)->processes_[index]; - } else { - LM_LOG_DEBUG() << "Unable to retrieve process configuration for process group" << pg_name - << "with index" << index; - } - - return result; -} - -std::optional ConfigurationManager::getOsProcessDependencies(const IdentifierHash& pg_name, - const uint32_t index) const { - std::optional result = std::nullopt; - - if (auto pg = getProcessGroupByNameAndIndex(pg_name, index)) { - result = &(*pg)->processes_[index].dependencies_; - } else { - LM_LOG_DEBUG() << "Unable to retrieve process dependencies for process group" << pg_name << "with index" - << index; - } - - return result; -} - -bool ConfigurationManager::initialize() { - bool result = false; // Assume failure by default - process_index_ = 0U; - LM_LOG_DEBUG() << "Loading LCM Configurations..."; - - // Check or set the environment variable - if (checkOrSetFlatConfigEnvVar(score::lcm::internal::kEnvVarName, score::lcm::internal::kEnvVarDefaultValue)) { - LM_LOG_DEBUG() << "ECUCFG_ENV_VAR_ROOTFOLDER set successfully"; - result = initializeSoftwareClusterConfigurations(); - - // Assign execution dependencies process based on index - AssignOsProcessIndexesInDependencyList(); - } else { - LM_LOG_DEBUG() << "Failed to set ECUCFG_ENV_VAR_ROOTFOLDER"; - } - - return result; -} - -void ConfigurationManager::deinitialize() { - for (auto& process_group : process_groups_) { - for (auto& process : process_group.processes_) { - for (size_t i = 0U; i < score::lcm::internal::kArgvArraySize && process.startup_config_.argv_[i] != nullptr; - ++i) { - // RULECHECKER_comment(1, 1, check_pointer_qualifier_cast_const, "Remove const for standard library with char type arguments.", true); - free(const_cast(process.startup_config_.argv_[i])); - process.startup_config_.argv_[i] = nullptr; - } - for (size_t i = 0U; process.startup_config_.envp_[i] != nullptr; ++i) { - // RULECHECKER_comment(1,1, check_stdlib_use_alloc, "compiler intrinsic calls", true_no_defect); - free(process.startup_config_.envp_[i]); - process.startup_config_.envp_[i] = nullptr; - } - } - } -} - -bool ConfigurationManager::initializeSoftwareClusterConfigurations() { - bool result = false; - - // Load software clusters - if (loadListOfSWClusters()) { - result = true; - for (uint_least8_t i = 0U; i < sw_clusters_.size(); i++) { - if (loadSWClusterConfiguration(i)) { - LM_LOG_DEBUG() << "Loading SWCL Nr." << static_cast(i) << "Succeeded"; - } else { - LM_LOG_ERROR() << "Failed to load SWCL Nr." << static_cast(i); - result = false; - } - } - } else { - LM_LOG_DEBUG() << "Failed to load software clusters"; - } - - return result; -} - -bool ConfigurationManager::loadSWClusterConfiguration(uint8_t sw_cluster_index) { - const auto data = read_flatbuffer_file("lm_demo.bin"); - if(!data) { - return false; - } - - // Extract root node from the loaded configuration - auto root_node = LMFlatBuffer::GetLMEcuCfg(data.get()); - if(!root_node) { - LM_LOG_DEBUG() << "Flatbuffer Parser: Empty configuration"; - return false; - } - - // Load machine configurations from the root node - if(!loadMachineConfigs(root_node, IdentifierHash(sw_clusters_[sw_cluster_index]))) { - LM_LOG_DEBUG() << "Flatbuffer Parser: Failed to read Machine Configuration"; - return false; - } - - if(!loadProcessConfigs(root_node)) { - LM_LOG_DEBUG() << "Flatbuffer Parser: Failed to read Process Configuration"; - return false; - } - - return true; -} - -bool ConfigurationManager::loadMachineConfigs(const LMFlatBuffer::LMEcuCfg* root_node, const IdentifierHash& cluster) { - bool result = false; - - const auto* mode_group = root_node ? root_node->ModeGroup() : nullptr; - - if (mode_group != nullptr) { - result = true; // Assume success if we reach this point - - for (uint32_t i = 0U; i < mode_group->size(); i++) { - if (!parseMachineConfigurations(mode_group->Get(i), cluster)) { - LM_LOG_WARN() << "Failed to parse mode group configurations"; - result = false; // Set result to false on failure - break; // Exit loop on failure - } - } - } else { - LM_LOG_DEBUG() << "loadMachineConfigs ModeGroup is null"; - } - - return result; -} - -bool ConfigurationManager::parseMachineConfigurations(const ModeGroup* node, const IdentifierHash& cluster) { - bool result = false; - - if (node) { - ProcessGroup process_group_data; - process_group_data.name_ = getStringViewFromFlatBuffer(node->identifier()); - process_group_data.sw_cluster_ = cluster; - LM_LOG_DEBUG() << "FlatBufferParser::getModeGroupPgName:" << std::string_view{getStringFromFlatBuffer(node->identifier())} - << "( IdentifierHash:" << process_group_data.name_.data() << ")"; - - if (process_group_data.name_ != score::lcm::IdentifierHash(std::string_view(""))) { - // Add process group name to the PG name list - process_group_names_.push_back(process_group_data.name_); - result = parseModeGroups(node, process_group_data); - } else { - LM_LOG_WARN() << "parseMachineConfigurations: Process group name is empty"; - } - } - return result; -} - -bool ConfigurationManager::parseModeGroups(const ModeGroup* node, ProcessGroup& process_group_data) { - bool result = false; - - const auto* mode_declaration_list = node ? node->modeDeclaration() : nullptr; - if (mode_declaration_list && (mode_declaration_list->size())) { - process_group_data.off_state_ = IdentifierHash("Off"); // default value if no other path is defined - - const flatbuffers::String* recovery_state_name = node->recoveryMode_name(); - if (recovery_state_name) { - process_group_data.recovery_state_ = getStringViewFromFlatBuffer(recovery_state_name); - } else { - process_group_data.recovery_state_ = IdentifierHash("Recovery"); // default value if nothing defined - } - - for (const auto* mode_declaration_node : *mode_declaration_list) { - const flatbuffers::String* flatbuffer_string = mode_declaration_node->identifier(); - if (flatbuffer_string) { - ProcessGroupState pg_state; - std::string string_name(flatbuffer_string->c_str(), flatbuffer_string->size()); - pg_state.name_ = getStringViewFromFlatBuffer(flatbuffer_string); - LM_LOG_DEBUG() << "FlatBufferParser::getModeGroupPgStateName:" - << std::string_view{flatbuffer_string->c_str(), flatbuffer_string->size()} - << "( IdentifierHash:" << pg_state.name_.data() << ")"; - process_group_data.states_.push_back(pg_state); - // Is this the "Off" state, i.e. does it end with "/Off" ? - auto str_len = string_name.length(); - if ((str_len > 3UL) && (0 == string_name.compare(str_len - 4UL, 4UL, "/Off"))) { - process_group_data.off_state_ = pg_state.name_; - } - } - } - - // Successfully parsed machine configurations - process_groups_.push_back(process_group_data); - result = true; - } else { - LM_LOG_DEBUG() << "parseMachineConfigurations: Mode declarations are not available or list is null"; - } - return result; -} - -bool ConfigurationManager::loadProcessConfigs(const LMFlatBuffer::LMEcuCfg* root_node) { - bool result = false; - - const auto* process = root_node ? root_node->Process() : nullptr; - - if (process != nullptr) { - result = true; // Assume success if we reach this point - - for (uint32_t i = 0U; i < process->size(); i++) { - if (!parseProcessConfigurations(process->Get(i))) { - LM_LOG_DEBUG() << "Failed to parse process configurations"; - result = false; // Mark failure if parsing fails - break; // Stop processing further if parsing fails - } - } - } else { - LM_LOG_DEBUG() << "Process node is null"; - } - - return result; -} - -static void setSchedulingParameters(const Process& node, const ProcessStartupConfig& config, OsProcess& instance) { - instance.startup_config_.cpu_mask_ = ConfigurationManager::kDefaultProcessorAffinityMask(); - instance.startup_config_.scheduling_policy_ = ConfigurationManager::kDefaultSchedulingPolicy; - instance.startup_config_.scheduling_priority_ = ConfigurationManager::kDefaultNormalSchedulingPriority; - auto attribute = config.schedulingPolicy(); - if (attribute != nullptr) { - if (strcasecmp("SCHED_FIFO", attribute->c_str()) == 0) { - instance.startup_config_.scheduling_policy_ = SCHED_FIFO; - instance.startup_config_.scheduling_priority_ = ConfigurationManager::kDefaultRealtimeSchedulingPriority; - } else if (strcasecmp("SCHED_RR", attribute->c_str()) == 0) { - instance.startup_config_.scheduling_policy_ = SCHED_RR; - instance.startup_config_.scheduling_priority_ = ConfigurationManager::kDefaultRealtimeSchedulingPriority; - } else if (strcasecmp("SCHED_OTHER", attribute->c_str()) == 0) { - instance.startup_config_.scheduling_policy_ = SCHED_OTHER; - } else { - LM_LOG_WARN() << "scheduling policy" << std::string_view{attribute->c_str(), attribute->size()} << "is not supported, using default"; - } - } - attribute = config.schedulingPriority(); - if (attribute != nullptr) { - instance.startup_config_.scheduling_priority_ = std::stoi(attribute->c_str()); - } - attribute = node.coremask(); - if (attribute != nullptr) { - instance.startup_config_.cpu_mask_ = static_cast(std::stoul(attribute->c_str()) & 0XFFFFFFFFUL); - } -} - -bool ConfigurationManager::parseProcessConfigurations(const Process* node) { - bool result = false; - - const auto* startup_config_list = node ? node->startupConfig() : nullptr; - - if (startup_config_list && (startup_config_list->size())) { - result = true; - for (const auto* startup_config_node : *startup_config_list) { - // Populate instance details based on startup_config_node data - OsProcess instance; - instance.process_number_ = process_index_; // Each instance gets a unique number - if (process_index_ < 0XFFFFFFFFU) { - process_index_++; - } - - setSchedulingParameters(*node, *startup_config_node, instance); - // Set executable path from node's path - instance.startup_config_.executable_path_ = getStringFromFlatBuffer(node->path()); - LM_LOG_DEBUG() << "parseProcessConfigurations: Process index:" << instance.process_number_ - << "executable_path_:" << instance.startup_config_.executable_path_; - - instance.startup_config_.short_name_ = node->identifier() ? node->identifier()->c_str() : "Unknown"; - instance.startup_config_.uid_ = node->uid() & 0x7FFFFFFFU; - instance.startup_config_.gid_ = node->gid() & 0x7FFFFFFFU; - - instance.startup_config_.security_policy_ = - getStringFromFlatBuffer(node->securityPolicyDetails()); // Set security policy if available - - // extracting supplementary group IDs from Process configuration - // and assigning them to this particular startup config (aka OsProcess) - auto supplementary_gids = node->sgids(); - size_t supplementary_gids_number = supplementary_gids ? supplementary_gids->size() : 0U; - if (supplementary_gids_number > 0U) { - instance.startup_config_.supplementary_gids_.reserve(supplementary_gids_number); - } - for (uint32_t i = 0U; i < (supplementary_gids_number & 0XFFFFFFFFU); i++) { - const ProcessSgid* sgid_conf = supplementary_gids->Get(i); - if (nullptr != sgid_conf) { - instance.startup_config_.supplementary_gids_.push_back(sgid_conf->sgid()); - } - } - - instance.startup_config_.comms_type_ = getCommsType(node, instance.startup_config_.short_name_.c_str()); - - // startup configs - result = setResourceLimits(*startup_config_node, instance); - instance.pgm_config_.is_self_terminating_ = isSelfTerminatingProcess( - startup_config_node->terminationBehavior(), instance.startup_config_.short_name_); - instance.pgm_config_.startup_timeout_ms_ = - std::chrono::milliseconds(startup_config_node->enterTimeoutValue()); - instance.pgm_config_.termination_timeout_ms_ = - std::chrono::milliseconds(startup_config_node->exitTimeoutValue()); - - auto execution_error_string = startup_config_node->executionError(); - if (execution_error_string) { - instance.pgm_config_.execution_error_code_ = - static_cast(std::stoi(execution_error_string->c_str())); - } else { - // default value - instance.pgm_config_.execution_error_code_ = kDefaultProcessExecutionError; - } - instance.pgm_config_.number_of_restart_attempts = node->numberOfRestartAttempts(); - - // Set process_id from node's identifier - instance.process_id_ = getStringViewFromFlatBuffer(node->identifier()); - - // Parse process arguments and environment variables - parseProcessArguments(startup_config_node->processArgument(), instance); - parseProcessEnvironmentVars(startup_config_node->environmentVariable(), instance); - - // Parse Execution dependency - parseExecutionDependency(startup_config_node->executionDependency(), instance); - - // Parse ProcessGroup dependency - parseProcessGroup(startup_config_node->processGroupStateDependency(), instance); - } - } else { - LM_LOG_DEBUG() << "parseProcessConfigurations: Startup configs are not available or list is null"; - } - - return result; -} - -void ConfigurationManager::parseProcessArguments( - const flatbuffers::Vector>* process_arg_list, - OsProcess& process_instance) { - // Initialize the argument index to 0 for setting the executable path - size_t arg_index = 0U; - - // Set the executable path as the first argument - process_instance.startup_config_.argv_[arg_index] = - strdup(process_instance.startup_config_.executable_path_.c_str()); - - // LM_LOG_DEBUG() << "Executable path set as the first argument:" << process_instance.executable_path_; - - // Increment the argument index for the next argument - ++arg_index; - - if (process_arg_list) { - // Convert the size of process_arg_list to size_t and log the number of arguments - size_t arg_count = static_cast(process_arg_list->size()); - - // Calculate the maximum number of arguments to process, considering the argv size limit - size_t max_args = std::min(arg_count, static_cast(score::lcm::internal::kMaxArg)); - - - // Check if the number of arguments exceeds the maximum allowed size and log a warning if it does - if (arg_count > static_cast(score::lcm::internal::kMaxArg)) { - LM_LOG_DEBUG() << "Number of process arguments exceeds maximum allowed size (kMaxArg =" - << static_cast(score::lcm::internal::kMaxArg) << "). Only the first" - << static_cast(score::lcm::internal::kMaxArg) << "arguments will be processed."; - } - - // Iterate through the process arguments and add them to the argv array - for (size_t i = 0U; i < max_args; ++i) { - auto process_arg_node = process_arg_list->Get(static_cast(i)); - - if (process_arg_node) { - // Convert the flatbuffer argument to a C string and add it to the argv array - auto argument = getStringFromFlatBuffer(process_arg_node->argument()); - // coverity[autosar_cpp14_a4_7_1_violation:FALSE] Arg count is checked above - no risk of wraparound. - process_instance.startup_config_.argv_[arg_index++] = strdup(argument); - } - } - } - - // the argv_ member is std::array and it is initlized so all elements - // are nullptr to begin with and so we don't need to append one. -} - -void ConfigurationManager::parseProcessEnvironmentVars( - const flatbuffers::Vector>* env_var_list, - OsProcess& process_instance) { - size_t env_index = 0U; - - if (env_var_list) { - // Convert the size of env_var_list to size_t and log the number of environment variables - size_t env_count = static_cast(env_var_list->size()); - // LM_LOG_DEBUG() << "Number of process environment variables:" << env_count; - - // Calculate the maximum number of environment variables to process, considering the envp size limit - size_t max_env = std::min(env_count, static_cast(score::lcm::internal::kMaxEnv)); - // LM_LOG_DEBUG() << "Number of process environment variables to process:" << max_env; - - // Check if the number of environment variables exceeds the maximum allowed size and log a warning if it does - if (env_count > static_cast(score::lcm::internal::kMaxEnv)) { - LM_LOG_WARN() << "Number of process environment variables exceeds maximum allowed size (kMaxEnv =" - << static_cast(score::lcm::internal::kMaxEnv) << "). Only the first" - << static_cast(score::lcm::internal::kMaxEnv) << "variables will be processed."; - } - - // Iterate through the process environment variables and add them to the envp array - for (size_t i = 0U; i < max_env; ++i) { - auto env_var_node = env_var_list->Get(static_cast(i)); - - if (env_var_node) { - auto key = getStringFromFlatBuffer(env_var_node->key()); - auto value = getStringFromFlatBuffer(env_var_node->value()); - - // Format environment variable as "key=value" - std::string env_str = std::string(key) + "=" + std::string(value); // TODO - - // coverity[autosar_cpp14_a4_7_1_violation:FALSE] Environment count is checked above - no risk of wraparound. - process_instance.startup_config_.envp_[env_index++] = strdup(env_str.c_str()); - } - } - } else { - // Log if the process environment variables list is null - // LM_LOG_DEBUG() << "Process environment variables list is not available"; - } - // Add a NULL terminator at the end of the array - process_instance.startup_config_.envp_[env_index] = nullptr; - // LM_LOG_DEBUG() << "Environment variable array null-terminated at index" << env_index; -} - -void ConfigurationManager::parseProcessGroup( - const flatbuffers::Vector>* process_pg_list, - const OsProcess& process_instance) { - if (process_pg_list) { - for (const auto& process_pg_node : *process_pg_list) { - if (process_pg_node) { - // Extract information from ProcessGroupStateDependency of flatconfig binary - ProcessGroupStateID pg_info; - pg_info.pg_name_ = getStringViewFromFlatBuffer(process_pg_node->stateMachine_name()); - pg_info.pg_state_name_ = getStringViewFromFlatBuffer(process_pg_node->stateName()); - LM_LOG_DEBUG() << "ParseProcessProcessGroup: id:::pg_name_:" << pg_info.pg_name_ - << ", pg_state_name_:" << pg_info.pg_state_name_; - - // Assign OsProcess instance to the process group - AssignOsProcessInstanceToProcessGroup(pg_info, process_instance); - } - } - // Successfully processed all process groups - } else { - LM_LOG_DEBUG() << "ParseProcessProcessGroup: Process process groups are not available"; - } -} - -void ConfigurationManager::parseExecutionDependency( - const flatbuffers::Vector>* process_dependency_list, - OsProcess& process_instance) { - if (process_dependency_list) { - for (const auto& process_dependency_node : *process_dependency_list) { - if (process_dependency_node) { - Dependency dep{}; - auto state_name = getStringViewFromFlatBuffer(process_dependency_node->stateName()); - dep.process_state_ = getProcessState(state_name); - dep.target_process_id_ = getStringViewFromFlatBuffer(process_dependency_node->targetProcess_identifier()); - LM_LOG_DEBUG() << "ParseProcessExecutionDependency: target process path:" - << std::string_view{getStringFromFlatBuffer(process_dependency_node->targetProcess_identifier())} - << "ID:" << dep.target_process_id_; - process_instance.dependencies_.push_back(dep); - - } - } - } else { - LM_LOG_DEBUG() << "ParseProcessExecutionDependency: Process execution dependencies are not available"; - } -} - -score::lcm::ProcessState ConfigurationManager::getProcessState(const IdentifierHash& state_name) { - score::lcm::ProcessState result = score::lcm::ProcessState::kIdle; - - if (state_name == static_cast(PROCESS_RUNNING_STATE)) { - result = score::lcm::ProcessState::kRunning; - } else if (state_name == static_cast(PROCESS_TERMINATED_STATE)) { - result = score::lcm::ProcessState::kTerminated; - } - - return result; -} - -ProcessGroup* ConfigurationManager::getProcessGroupByID(const IdentifierHash& pg_name) const { - const ProcessGroup* result = nullptr; - - if (!process_groups_.empty()) { - auto it = find_if(process_groups_.begin(), process_groups_.end(), - [&pg_name](const ProcessGroup& pg) { return pg.name_ == pg_name; }); - - if (it != process_groups_.end()) { - result = &(*it); - } - } - - // RULECHECKER_comment(1, 1, check_pointer_qualifier_cast_const, "Remove const for standard library with char type arguments.", true); - return const_cast(result); -} - -ProcessGroupState* ConfigurationManager::getProcessGroupStateByID(const ProcessGroupStateID& pg_id) const { - ProcessGroupState* result = nullptr; - - ProcessGroup* pg = getProcessGroupByID(pg_id.pg_name_); - - if (pg) { - auto it = find_if(pg->states_.begin(), pg->states_.end(), - [&pg_id](const ProcessGroupState& state) { return state.name_ == pg_id.pg_state_name_; }); - - if (it != pg->states_.end()) { - result = &(*it); - } - } - - return result; -} - -ProcessGroupState* ConfigurationManager::getProcessGroupStateByID(ProcessGroup& pg, - const IdentifierHash& state_name) const { - ProcessGroupState* foundState = nullptr; - - auto it = find_if(pg.states_.begin(), pg.states_.end(), - [&state_name](const ProcessGroupState& state) { return state.name_ == state_name; }); - - if (it != pg.states_.end()) { - foundState = &(*it); - } - - return foundState; -} - -void ConfigurationManager::AssignOsProcessInstanceToProcessGroup(const ProcessGroupStateID& process_pg, - const OsProcess& process_instance) { - // Find the process group by name - auto pg = getProcessGroupByID(process_pg.pg_name_); - if (pg != nullptr) { - // Find the process group state by name within the process group - auto state = getProcessGroupStateByID(*pg, process_pg.pg_state_name_); - if (state != nullptr) { - uint32_t index_in_pg; - // Add the process instance to the process group if it's not already there - auto it = find_if(pg->processes_.begin(), pg->processes_.end(), - [&process_instance](const OsProcess& inst) -> bool { - return process_instance.process_number_ == inst.process_number_; - }); - if (it == pg->processes_.end()) { - // get index and insert new value - index_in_pg = static_cast(pg->processes_.size() & 0XFFFFFFFFUL); - pg->processes_.push_back(process_instance); - } else { - // already there, calculate index of the entry - index_in_pg = static_cast((it - pg->processes_.begin()) & 0X7FFFFFFFL); - } - // Add the process index if it doesn't already exist in the process group state - if (find(state->process_indexes_.begin(), state->process_indexes_.end(), index_in_pg) == - state->process_indexes_.end()) { - state->process_indexes_.push_back(index_in_pg); - } - } else { - LM_LOG_WARN() << "Process group state not found:" << process_pg.pg_state_name_; - } - } else { - LM_LOG_WARN() << "Process group not found:" << process_pg.pg_name_; - } -} - -void ConfigurationManager::AssignOsProcessIndexesInDependencyList() { - for (auto& pg : process_groups_) { - for (size_t process_index = 0U; process_index < pg.processes_.size(); ++process_index) { - auto& process = pg.processes_[process_index]; - UpdateOsProcessIndexInDependencyList(pg, process.dependencies_); - } - } -} - -void ConfigurationManager::UpdateOsProcessIndexInDependencyList(ProcessGroup& pg, DependencyList& dep_list) { - // Lambda to process each dependency - auto processDependency = [&](Dependency& dependency) { - // Lambda to match target process ID and update index - auto matchAndUpdateOsProcessIndex = [&]() { - for (size_t process_index = 0U; process_index < pg.processes_.size(); ++process_index) { - auto& os_process = pg.processes_[process_index]; - - if (dependency.target_process_id_ == os_process.process_id_) { - dependency.os_process_index_ = static_cast(process_index & 0xFFFFFFFFUL); - - return; // Exit the loop once the update is done - } - } - }; - - matchAndUpdateOsProcessIndex(); - }; - - // Process each dependency in the dependency list - for (auto& dependency : dep_list) { - processDependency(dependency); - } -} - -bool ConfigurationManager::checkOrSetFlatConfigEnvVar(const std::string& name, const std::string& path) { - bool result = false; - const char* value = getenv(name.c_str()); - - if (value && strlen(value)) { - LM_LOG_DEBUG() << name << "already set. Current value:" << std::string_view{value}; - result = true; - } else { - if (setenv(name.c_str(), path.c_str(), overwrite_) == 0) { - result = true; - } else { - LM_LOG_DEBUG() << name.c_str() << "not set, so default flat config binary path loaded"; - } - } - - return result; -} - -bool ConfigurationManager::loadListOfSWClusters() { - bool result = false; - - // Default value for demonstration - sw_clusters_.clear(); - sw_clusters_.emplace_back("DefaultSoftwareCluster"); - result = true; - - return result; -} - -osal::CommsType ConfigurationManager::getfunctionClusterAffiliation(osal::CommsType current_comms, - const char* attribute) { - osal::CommsType comms_type = current_comms; - - if (attribute && std::string_view(attribute) == "STATE_MANAGEMENT") { - comms_type = osal::CommsType::kControlClient; - LM_LOG_DEBUG() << "Process is STATE_MANAGEMENT function Cluster Affiliation"; - } else if (attribute && std::string_view(attribute) == "PLATFORM_HEALTH_MANAGEMENT") { - //TODO - example introduce PHM enum. - LM_LOG_DEBUG() << "Process is PLATFORM_HEALTH_MANAGEMENT function Cluster Affiliation"; - } else if (attribute && std::string_view(attribute) == "LAUNCH_MANAGEMENT") { - comms_type = osal::CommsType::kLaunchManager; - LM_LOG_DEBUG() << "Process is LAUNCH_MANAGEMENT function Cluster Affiliation"; - } else { - LM_LOG_DEBUG() << "Process is NOT associated with any function Cluster Affiliation"; - } - - return comms_type; -} - -// TODO - This is workaround solution for comms_type. Since reporting behaviour -// and function cluster affiliation both are different config. we need to seperate it. -osal::CommsType ConfigurationManager::getCommsType(const Process* node, const char* short_name) { - osal::CommsType comms_type = osal::CommsType::kNoComms; - - if (node != nullptr) { - // Check reporting behavior - comms_type = isReportingProcess(node->executable_reportingBehavior(), short_name); - - // Check function cluster affiliation - comms_type = - getfunctionClusterAffiliation(comms_type, getStringFromFlatBuffer(node->functionClusterAffiliation())); - } - return comms_type; -} - -osal::CommsType ConfigurationManager::isReportingProcess(const ExecutionStateReportingBehaviorEnum reporting_behaviour, - const std::string_view process_name) { - osal::CommsType reporting_status = osal::CommsType::kNoComms; - - if (reporting_behaviour == ExecutionStateReportingBehaviorEnum::ExecutionStateReportingBehaviorEnum_ReportsExecutionState) { - reporting_status = osal::CommsType::kReporting; - LM_LOG_DEBUG() << "Process" << process_name << "is Reporting execution state"; - } else { - // ExecutionStateReportingBehaviorEnum::DoesNotReportExecutionState - LM_LOG_DEBUG() << "Process" << process_name << "is NOT Reporting execution state"; - } - - return reporting_status; -} - -bool ConfigurationManager::isSelfTerminatingProcess(const TerminationBehaviorEnum termination_behavior, - const std::string_view process_name) { - bool termination_status = false; - - if (termination_behavior == TerminationBehaviorEnum::TerminationBehaviorEnum_ProcessIsSelfTerminating) { - termination_status = true; - LM_LOG_DEBUG() << "Process" << process_name << "is Self terminating"; - } else { - // TerminationBehaviorEnum::ProcessIsNotSelfTerminating - LM_LOG_DEBUG() << "Process" << process_name << "is NOT Self terminating"; - } - - return termination_status; -} - -std::optional ConfigurationManager::getProcessGroupByNameAndIndex(const IdentifierHash& pg_name, - const uint32_t index) const { - std::optional result = std::nullopt; - - auto pg = getProcessGroupByID(pg_name); - - if (pg) { - if (index < pg->processes_.size()) { - result = pg; - } else { - LM_LOG_DEBUG() << "Process index" << index << "is out of bounds in process group" << pg_name; - } - } else { - LM_LOG_DEBUG() << "Process group not found:" << pg_name; - } - - return result; -} - -IdentifierHash ConfigurationManager::getStringViewFromFlatBuffer(const flatbuffers::String* flat_string) { - return flat_string ? IdentifierHash{flat_string->c_str()} : IdentifierHash{}; -} - -const char* ConfigurationManager::getStringFromFlatBuffer(const flatbuffers::String* flat_string) { - return flat_string ? flat_string->c_str() : ""; -} - -} // namespace lcm - -} // namespace internal - -} // namespace score diff --git a/score/launch_manager/daemon/src/configuration/configuration_manager.hpp b/score/launch_manager/daemon/src/configuration/configuration_manager.hpp deleted file mode 100644 index 57ee09627..000000000 --- a/score/launch_manager/daemon/src/configuration/configuration_manager.hpp +++ /dev/null @@ -1,485 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ - - -#ifndef CONFIGURATIONMANAGER_HPP_INCLUDED -#define CONFIGURATIONMANAGER_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include -#include "score/mw/launch_manager/common/identifier_hash.hpp" -#include "score/mw/launch_manager/common/constants.hpp" -#include "score/mw/launch_manager/common/process_group_state_id.hpp" -#include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/process_state_client/posix_process.hpp" - -#include "score/mw/launch_manager/configuration/lm_flatcfg_generated.h" - -namespace score { - -namespace lcm { - -namespace internal { - -using IdentifierHash = score::lcm:: - IdentifierHash; ///< Defines a type alias 'IdentifierHash' for the type 'score::lcm::IdentifierHash'. Type that represents an identity or identifier. Usually this is a path to a short name. - -/// @brief Represents the configuration settings for a process group manager. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -struct PgManagerConfig final { - bool is_self_terminating_; ///< true if the adaptive application may terminate without being first asked - std::chrono::milliseconds - startup_timeout_ms_; ///< Number of milliseconds to wait for kRunning before flagging an error - std::chrono::milliseconds - termination_timeout_ms_; ///< Number of milliseconds to wait for process to terminate after requesting termination - uint32_t number_of_restart_attempts; ///< Number of times to attempt restart if the initial attempt fails - uint32_t execution_error_code_; ///< Code to report if this process fails -}; - -/// @brief Represents process dependency in a particular process group associated process. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -struct Dependency final { - score::lcm::ProcessState process_state_; ///< The state of the other process upon which starting of this process depends. - IdentifierHash target_process_id_; ///< The ID of the target process this dependency is associated with. - uint32_t os_process_index_; ///< The index of the OS process in the target process list. -}; - -using DependencyList = std::vector; - -/// @brief Represent configuration needed to start operating system process, plus identifier of a process for which this startup configuration was defined / configured. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -struct OsProcess final { - IdentifierHash process_id_; ///< id of a Process. - uint32_t process_number_; ///< unique number for this process & startup configuration combination - osal::OsalConfig startup_config_{}; ///< Startup configuration. - PgManagerConfig pgm_config_; ///< Process group manager operations configuration. - DependencyList dependencies_; ///< List of dependencies for each OS process in a specific process group. -}; - -/// @brief Represents configuration of a process group state. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -struct ProcessGroupState final { - IdentifierHash name_; ///< Name of a process group state. - std::vector - process_indexes_; ///< Processes that should be started / run in this process group state. It is an array of indexes (aka pointers) to the processes managed by a process group. -}; - -/// @brief Represents a process group configuration. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -struct ProcessGroup final { - IdentifierHash name_; ///< Name of a process group. - IdentifierHash sw_cluster_; ///< Software cluster to which this process group belongs - IdentifierHash off_state_; ///< ID of the "Off" state for this process group - IdentifierHash recovery_state_; ///< ID of the recovery state for this process group - std::vector states_; ///< States configured for this process group. - std::vector - processes_; ///< Processes that are managed (started / stopped) by this process group. -}; - -/// -/// @brief Manages the configuration of the machine. -/// -/// ConfigurationManager is responsible for the entire lifecycle of configuration. -/// It loads configuration from persistent storage, verify that configuration was not tampered with and then makes that data available (read only) to the rest of Launch Manager. -/// It is also responsible for rereading (updating) configuration during software update. -// RULECHECKER_comment(1, 1, check_incomplete_data_member_construction, "wi 45913 - This struct is POD, which doesn't have user-declared constructor. The rule doesn’t apply.", false) -class ConfigurationManager final { - // using namespace ::score::internal::ucm::ipc; - public: - /// @brief Initializes the configuration manager. - /// - /// This function is responsible for loading the configurations. - /// It performs the following main tasks: - /// - Checks or sets the FlatBuffer configuration environment variable. - /// - Obtain the list of software clusters. If this is successful, load the first software cluster from the list. - /// - Gets every element in the configuration. keeps a local reference to every configuration element for easy access. - /// TODO: Add more details about the memory allocation. - /// - /// @return Returns true if the configurations were loaded successfully, false otherwise. - bool initialize(); - - /// @brief Deinitializes the configuration manager. - /// - /// This function is responsible for performing any necessary cleanup or deinitialization tasks - /// for the configuration manager. It should be called when the configuration manager is no longer - /// needed or when the application is shutting down. - void deinitialize(); - - /// @brief Get a list of process groups configured for this Machine. - /// @return Returns a pointer to a vector of process groups. - std::optional*> getListOfProcessGroups() const; - - /// @brief Get the software cluster id for a given process group id. - /// @param process_group_id the IdentifierHash of the process group - /// @return Returns the IdentifierHash of the software cluster to which the process group belongs. - std::optional getSoftwareCluster(const IdentifierHash& process_group_id) const; - - /// @brief Reload the configuration for a particular software cluster - /// @param action Action to take (install, remove, or update) - /// @param sw_cluster_id The sofware cluster to process - /// @return Returns true if the configurations were loaded successfully, false otherwise. - // bool reloadConfiguration( - // const score::internal::ucm::ipc::Message::Action action, - // const IdentifierHash& cluster_id ); - - /// @brief Get the number of OS processes configured for a particular process group. - /// @param[in] pg_name The name of the process group. - /// @return Returns the number of OS processes. - /// If process group does not exist then there will be no return value. - std::optional getNumberOfOsProcesses(const IdentifierHash& pg_name) const; - - /// @brief Get the ID of the "Off" state for a particular process group. - /// @param[in] pg_name The name of the process group. - /// @return Returns the ID of the "Off" state. - /// If process group does not exist a default value of IdentifierHash("Off") is returned. - IdentifierHash getNameOfOffState(const IdentifierHash& pg_name) const; - - /// @brief Get the ID of the recovery state for a particular process group. - /// @param[in] pg_name The name of the process group. - /// @return Returns the ID of the recovery state. - /// If process group does not exist a default value of IdentifierHash("Recovery") is returned. - IdentifierHash getNameOfRecoveryState(const IdentifierHash& pg_name) const; - - /// @brief Get the startup state for the main process group. - /// @return Return the startup state of the main process group, as specified by AUTOSAR. - std::optional getMainPGStartupState() const; - - /// @brief Get a list of processes configured to run in this process group state. - /// @param[in] process_group_state_id The ID of the process group state for which to retrieve the list of process IDs. - /// @return Returns a pointer to a vector of process indexes. - /// Process group state 'Off' will have vector of size 0. - /// If Process group does not exist then there will be no return value. - std::optional*> getProcessIndexesList( - const ProcessGroupStateID& process_group_state_id) const; - - /// @brief Get startup configuration for a given process. - /// @param[in] pg_name_ The name of the process group for which to retrieve the OS Configurations. . - /// @param[in] index The index of the OS process. - /// @return Returns a pointer to an OSProcess. - /// If index/process group does not exist there will be no return value. - std::optional getOsProcessConfiguration(const IdentifierHash& pg_name_, - const uint32_t index) const; - - /// @brief Get dependencies of an OS process within a specific process group. - /// - /// Retrieves the dependencies associated with an OS process identified by its index - /// within a specified process group. Dependencies include the current state of the process - /// and any related process indices that need to be managed together. - /// - /// @param[in] process_group_name The name of the process group containing the OS process. - /// @param[in] index The index of the OS process within the process group. - /// @return An optional vector of Dependency objects representing process dependencies, - /// or an empty optional if the process group or process index does not exist. - std::optional getOsProcessDependencies(const IdentifierHash& process_group_name, - const uint32_t index) const; - - /// @brief default value for the process execution error, in case it is not defined in the configuration - static const uint32_t kDefaultProcessExecutionError; - - /// @brief default value for processor affinity mask in case it is not defined in the configuration - static uint32_t kDefaultProcessorAffinityMask(); - - /// @brief default value for scheduling policy in case it is not defined in the configuration - static const int32_t kDefaultSchedulingPolicy; - - /// @brief default value for scheduling priority in case if is not defined in the configuration and - /// if the process is running in real-time scheduling mode. - static const int32_t kDefaultRealtimeSchedulingPriority; - - /// @brief default value for scheduling priority in case if is not defined in the configuration and - /// if the process is running in normal scheduling mode. - static const int32_t kDefaultNormalSchedulingPriority; - - private: - /// @brief Initializes the LCM configurations for the software clusters. - /// This function loads the list of software clusters and then loads the LCM configurations - /// for the specified software cluster index. It sets the success flag to true if all steps - /// are completed successfully. - /// @return true if the initialization is successful, false otherwise. - bool initializeSoftwareClusterConfigurations(); - - /// @brief Load the LCM configurations for a specific software cluster. - /// This function loads the LCM configurations for the software cluster identified by the given index. - /// @param[in] index The index of the software cluster for which to load the LCM configurations. - /// @return `true` if the LCM configurations were successfully loaded, `false` otherwise. - bool loadSWClusterConfiguration(uint8_t index); - - /// @brief Load the software clusters from the flat configuration. - /// This function loads the list of software clusters from the flat configuration. - /// It parses the root node and extracts machine-specific configurations for further processing. - /// @param[in] index The index of the software cluster for which to load the LCM configurations. - /// @return `true` if the software clusters were successfully loaded and stored, `false` otherwise. - bool loadListOfSWClusters(); - - /// @brief Load machine configurations from the provided root node. - /// This function loads machine configurations from the specified root node of the LCM EcuCfg. - /// It retrieves and stores the software clusters internally for further processing. - /// @param[in] root_node Pointer to the root node of the LCM EcuCfg containing machine configurations. - /// @param[in] cluster ID if the software cluster to store in each process group structure - /// @return `true` if machine configurations were successfully loaded and processed, `false` otherwise. - bool loadMachineConfigs(const LMFlatBuffer::LMEcuCfg* root_node, const IdentifierHash& cluster); - - /// @brief Load process configurations from the provided root node. - /// This function loads process configurations from the specified root node of the LCM EcuCfg. - /// It parses the root node and extracts process-specific configurations for further processing. - /// @param[in] root_node Pointer to the root node of the LCM EcuCfg containing process configurations. - /// @return `true` if process configurations were successfully loaded and processed, `false` otherwise. - bool loadProcessConfigs(const LMFlatBuffer::LMEcuCfg* root_node); - - /// @brief Parses mode groups from the provided ModeGroup node and updates the ProcessGroup. - /// This function iterates through the mode declarations in the ModeGroup node and creates ProcessGroupState objects - /// for each mode declaration. It then adds these states to the provided ProcessGroups. If the mode declaration - /// list is empty or null, a warning is logged. - /// @param node The ModeGroup node containing mode group configurations. - /// @param process_group_data The ProcessGroup data to update with parsed configurations. - /// @return true if the mode groups are successfully parsed and added to the ProcessGroup data, false otherwise. - bool parseModeGroups(const LMFlatBuffer::ModeGroup* node, ProcessGroup& process_group_data); - - /// @brief Parse machine configurations from the provided ModeGroup node. - /// This function parses machine configurations from the specified ModeGroup node in the LCM FlatBuffer data. - /// @param[in] node Pointer to the ModeGroup node containing machine configurations. - /// @param[in] cluster ID if the software cluster to store in each process group structure - /// @return `true` if machine configurations were successfully parsed, `false` otherwise. - bool parseMachineConfigurations(const LMFlatBuffer::ModeGroup* node, const IdentifierHash& cluster); - - /// @brief Parse process configurations from the provided Process node. - /// This function parses process configurations from the specified Process node in the LCM FlatBuffer data. - /// @param[in] node Pointer to the Process node containing machine configurations. - /// @return `true` if process configurations were successfully parsed, `false` otherwise. - bool parseProcessConfigurations(const LMFlatBuffer::Process* node); - - /// @brief Parse process arguments from a list of FlatBuffer process argument nodes. - /// This function parses process arguments from the provided list of FlatBuffer process argument nodes - /// and populates the given OsProcess instance with the parsed arguments. - /// @param[in] process_arg_list Pointer to a vector of FlatBuffer process argument nodes. - /// @param[out] process_instance Reference to the OsProcess instance where parsed arguments will be stored. - void parseProcessArguments( - const flatbuffers::Vector>* process_arg_list, - OsProcess& process_instance); - - /// @brief Parse environment variables from a list of FlatBuffer environment variable nodes. - /// This function parses environment variables from the provided list of FlatBuffer environment variable nodes - /// and populates the given OsProcess instance with the parsed variables. - /// @param[in] env_var_list Pointer to a vector of FlatBuffer environment variable nodes. - /// @param[out] process_instance Reference to the OsProcess instance where parsed environment will be stored. - void parseProcessEnvironmentVars( - const flatbuffers::Vector>* env_var_list, - OsProcess& process_instance); - - /// @brief Parse process group dependencies of processes from a list of FlatBuffer process process group state dependency nodes. - /// This function parses process group dependencies from the provided list of FlatBuffer process process group state dependency nodes - /// and associates the specified OsProcess instance with the relevant process groups. - /// @param[in] process_pg_list Pointer to a vector of FlatBuffer process process group state dependency nodes. - /// @param[out] process_instance Reference to the OsProcess instance where parsed environment will be stored. - /// @return `true` if process group dependencies were successfully parsed and associated, `false` otherwise. - void parseProcessGroup( - const flatbuffers::Vector>* - process_pg_list, - const OsProcess& process_instance); - - /// @brief Parses execution dependencies from a FlatBuffer list and updates the provided OsProcess instance. - /// This function processes a list of `ProcessExecutionDependency` objects from the FlatBuffer and updates - /// the specified `OsProcess` instance to reflect these dependencies. Dependencies are used to manage - /// relationships between different processes. - /// @param[in] process_dependency_list Pointer to a vector of `ProcessExecutionDependency` objects from the FlatBuffer. - /// @param[out] process_instance Reference to the `OsProcess` instance that will be updated with the parsed dependencies. - void parseExecutionDependency( - const flatbuffers::Vector>* - process_dependency_list, - OsProcess& process_instance); - - /// @brief Retrieves the process state enumeration based on the given state name. - /// This function looks up the `ProcessState` enumeration value corresponding to the provided state name. - /// The state name is expected to match one of the defined `ProcessState` values. - /// @param[in] state_name The name of the process state as an `IdentifierHash`. - /// @return The `ProcessState` enumeration value associated with the state name. If the state name does not match - /// any defined states, the function returns an undefined or default state. - score::lcm::ProcessState getProcessState(const IdentifierHash& state_name); - - /// @brief Get a pointer to a ProcessGroup by its ID. - /// This function retrieves a pointer to a ProcessGroup identified by the process group name ID. - /// @param[in] pg_name The ID of the ProcessGroup to retrieve. - /// @return A pointer to the ProcessGroup if found, or nullptr if not found. - ProcessGroup* getProcessGroupByID(const IdentifierHash& pg_name) const; - - /// @brief Get a pointer to a ProcessGroupState within a specified ProcessGroup by its ID. - /// This function retrieves a pointer to a ProcessGroupState identified by the state name ID within the given ProcessGroup pointer. - /// @param[in] pg The ProcessGroup in which to search for the ProcessGroupState. - /// @param[in] state_name The ID of the ProcessGroupState to retrieve. - /// @return A pointer to the ProcessGroupState if found within the ProcessGroup, or nullptr if not found. - ProcessGroupState* getProcessGroupStateByID(ProcessGroup& pg, const IdentifierHash& state_name) const; - - /// @brief Get a pointer to a ProcessGroupState by its ID. - /// This function retrieves a pointer to a ProcessGroupState identified by the PG state ID. - /// @param[in] pg_id The ID object containing information to identify the ProcessGroupState.. - /// @return A pointer to the ProcessGroupState if found, or nullptr if not found. - ProcessGroupState* getProcessGroupStateByID(const ProcessGroupStateID& pg_id) const; - - /// @brief Retrieves a pointer to a ProcessGroup based on its name and index. - /// This function searches for a `ProcessGroup` within the list of process groups based on the provided - /// process group name and index. It returns a pointer to the `ProcessGroup` if found; otherwise, it returns - /// `nullptr`. The index is used to specify a particular `ProcessGroup` if there are multiple process groups - /// with the same name. - /// @param[in] pg_name The name of the process group as an `IdentifierHash`. - /// @param[in] index The index of the process group within the list of process groups. - /// @return A pointer to the `ProcessGroup` if it exists, or `nullptr` if no matching process group is found - /// with the given name and index. - std::optional getProcessGroupByNameAndIndex(const IdentifierHash& pg_name, - const uint32_t index) const; - - /// @brief Assign an OsProcess instance to a ProcessGroupState identified by ID. - /// This function assigns the OsProcess instance to a ProcessGroup and process index to ProcessGroupState. - /// @param[in] pg_id The ID object containing information to identify the ProcessGroup and it's State. - /// @param[in] process_instance The OsProcess instance to assign to the ProcessGroup - void AssignOsProcessInstanceToProcessGroup(const ProcessGroupStateID& pg_id, const OsProcess& process_instance); - - /// @brief Check or set a flat configuration environment variable. - /// This function checks the existence of a flat configuration environment variable with the specified name. - /// If the variable exists and its value is different from the provided value, it updates the variable's value. - /// If the variable does not exist, it sets the variable with the provided name and value - /// @param[in] name The name of the environment variable to check or set - /// @param[in] value The value to set for the environment variable. - /// @return `true` if the environment variable was successfully checked or set, `false` otherwise. - bool checkOrSetFlatConfigEnvVar(const std::string& name, const std::string& value); - - /// @brief Get the value of an environment variable by name. - /// This function is wrapper for getenv() system call and it retrieves the value of the environment variable identified by the specified name. - /// @param[in] name The name of the environment variable to check or set - /// @return The value of the environment variable as a String, or an empty string if not found. - std::string getEnvVar(const std::string& name) const; - - /// @brief Set or update an environment variable with the specified name and value. - /// This function is wrapper for setenv() system call and it sets or updates an environment variable with the provided name and value. - /// @param[in] name The name of the environment variable to set. - /// @param[in] value The value to assign to the environment variable. - /// @param[in] overwrite Flag indicating whether to overwrite an existing variable. - /// @return Zero if the operation succeeds, or -1 if an error occurs (e.g., permission denied). - int setEnvVar(const std::string& name, const std::string& value, int overwrite) const; - - /// @brief Get an IdentifierHash from a FlatBuffer string. - /// This function extracts an `IdentifierHash` from the provided FlatBuffer string. - /// @param[in] flat_string Pointer to the FlatBuffer string from which to extract the `IdentifierHash`. - /// @return The extracted `IdentifierHash` or an empty string if `flat_string` is nullptr. - IdentifierHash getStringViewFromFlatBuffer(const flatbuffers::String* flat_string); - - /// @brief Extract a C-style string from a FlatBuffer string. - /// This function retrieves a C-style (null-terminated) string from the provided FlatBuffer string. - /// If the `flat_string` is nullptr, it returns a pointer to an empty string. - /// @param[in] flat_string Pointer to the FlatBuffer string from which to extract the C-style string. - /// @return The extracted C-style string or an empty string if `flat_string` is nullptr. - const char* getStringFromFlatBuffer(const flatbuffers::String* flat_string); - - /// @brief Determines if the process reports its execution state. - /// This function checks the reporting behavior of a process and logs an appropriate message. - /// It returns `true` if the process reports its execution state and `false` otherwise. - /// @param[in] reporting_behaviour The reporting behavior of the process, represented as an enumerator of type LMFlatBuffer::ExecutionStateReportingBehaviorEnum. - /// @param[in] process_name The name of the process as a FlatBuffer string. - /// @return `kReporting` if the process reports its execution state, `kNoComms` otherwise. - osal::CommsType isReportingProcess(const LMFlatBuffer::ExecutionStateReportingBehaviorEnum reporting_behaviour, - const std::string_view process_name); - - /// @brief Determines the communication type for the process. - /// This function evaluates the process configuration to determine the appropriate communication type. - /// It checks the reporting behavior of the process and the function cluster affiliation to establish whether - /// a communication channel is needed and if it involves Control Client management. - /// @param[in] node A pointer to the process configuration node from which the communication type is derived. - /// @param[in] short_name Short name of the process - /// @return The communication type as an enumerator of type `osal::CommsType`. Possible values are `kNoComms`, - /// `kReporting`, or `kControlClient`. - osal::CommsType getCommsType(const LMFlatBuffer::Process* node, const char* short_name); - - /// @brief Determine the function cluster affiliation and update the communication type accordingly. - /// This function examines the given function cluster attribute and adjusts the current communication type if the process - /// belongs to a specific function cluster, such as "STATE_MANAGEMENT" or "PLATFORM_HEALTH_MANAGEMENT". - /// @param[in] current_comms The current communication type, which will be updated based on the function cluster affiliation. - /// @param[in] attribute A C-style string representing the function cluster affiliation of the process. - /// @return The updated communication type based on the function cluster affiliation. - osal::CommsType getfunctionClusterAffiliation(osal::CommsType current_comms, const char* attribute); - - /// @brief Determines if the process is self-terminating. - /// This function checks the termination behavior of a process and logs an appropriate message. - /// It returns `true` if the process is self-terminating and `false` otherwise. - /// @param[in] termination_behavior The termination behavior of the process, represented as an enumerator of type LMFlatBuffer::TerminationBehaviorEnum. - /// @param[in] process_name The name of the process as a FlatBuffer string. - /// @return `true` if the process is self-terminating, `false` otherwise. - bool isSelfTerminatingProcess(const LMFlatBuffer::TerminationBehaviorEnum termination_behavior, - const std::string_view process_name); - - /// @brief Assigns OS process indexes in the dependency list - /// This function assigns process indexes to each OS process in the dependency list - /// to ensure proper tracking of process dependencies. - void AssignOsProcessIndexesInDependencyList(); - - /// @brief Updates OS process indexes in the dependency list for a given process group. - /// This function updates the OS process indexes in the dependency list of the specified process group - /// to reflect the correct dependencies and relationships between processes. - /// @param[in] pg Reference to the ProcessGroup object for which to update the dependency list. - /// @param[in] dep_list Reference to the DependencyList object containing the dependencies to be updated. - void UpdateOsProcessIndexInDependencyList(ProcessGroup& pg, DependencyList& dep_list); - - /// @brief Root node of the LCM FlatBuffer configuration. - /// This member variable holds a pointer to the root node of the LCM FlatBuffer configuration, - /// which represents the top-level node of the parsed LCM configuration data. - /// It is initialized to nullptr by default. - const LMFlatBuffer::LMEcuCfg* root_node_{}; - - /// @brief List of software cluster identifiers. - /// This member variable represents a vector of strings that stores the identifiers of software clusters. - std::vector sw_clusters_{}; - - /// @brief List of Process groups Of the Machine. - /// This member variable represents a vector that stores instances of the ProcessGroup structure, - /// which encapsulate information about process groups. - std::vector process_groups_{}; - - /// @brief Vector of identifiers for process group names. - /// This member variable represents a vector that stores identifiers corresponding to process group names. - std::vector process_group_names_{}; - - /// @brief Default startup state identifier for a machine process group. - /// This member variable represents a predefined `ProcessGroupStateID` instance that identifies the startup state of a machine process group. - /// It is initialized with the names "MainPG" (process group name) and "Startup" (state name). - ProcessGroupStateID main_pg_startup_state_{static_cast("MainPG"), - static_cast("MainPG/Startup")}; - - /// @brief Unique Process index for OS process instance for specific startup configs - /// This member variable represents the index of the OS process instance with unique startup config. - /// It is initialized to 0 and typically incremented to assign different indices to distinct OS process instances. - uint32_t process_index_ = 0; - - /// @brief Flag indicating whether to overwrite existing environment variables. - /// This member variable represents a constant integer used as a flag to control the behavior - /// of setting environment variables. A value of 1 indicates that existing environment variables - /// should be overwritten when setting a new value. - const int overwrite_ = 1; - - /// @brief Execution depedency string representing the running dependency state of the process - /// This static member variable will stores the string "Running" to represent the running state. - static const char* PROCESS_RUNNING_STATE; - - /// @brief Execution depedency string representing the terminated dependency state of the process. - /// This static member variable will stores the string "Terminated" to represent the terminated state. - static const char* PROCESS_TERMINATED_STATE; -}; - -} // namespace lcm - -} // namespace internal - -} // namespace score - -#endif /// CONFIGURATIONMANAGER_HPP_INCLUDED diff --git a/score/launch_manager/daemon/src/process_group_manager/BUILD b/score/launch_manager/daemon/src/process_group_manager/BUILD index b5fa09543..c1986eeaf 100644 --- a/score/launch_manager/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/daemon/src/process_group_manager/BUILD @@ -59,7 +59,7 @@ cc_library( "//score/launch_manager/daemon/src/common:identifier_hash", "//score/launch_manager/daemon/src/common/concurrency:mpmc_concurrent_queue", "//score/launch_manager/daemon/src/common/concurrency:workerthread", - "//score/launch_manager/daemon/src/configuration:configuration_manager", + "//score/launch_manager/daemon/src/configuration:configuration_adapter", "//score/launch_manager/daemon/src/control:control_client_channel", "//score/launch_manager/daemon/src/osal:ipc_comms", "//score/launch_manager/daemon/src/process_group_manager/details:graph", diff --git a/score/launch_manager/daemon/src/process_group_manager/details/BUILD b/score/launch_manager/daemon/src/process_group_manager/details/BUILD index 679ab14ca..39353452b 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/BUILD +++ b/score/launch_manager/daemon/src/process_group_manager/details/BUILD @@ -20,7 +20,7 @@ cc_library( visibility = ["//score/launch_manager/daemon/src/process_group_manager:__pkg__"], deps = [ ":safe_process_map", - "//score/launch_manager/daemon/src/configuration:configuration_manager", + "//score/launch_manager/daemon/src/configuration:configuration_adapter", "//score/launch_manager/daemon/src/control:control_client_channel", "//score/launch_manager/daemon/src/osal:ipc_comms", "//score/launch_manager/daemon/src/osal:semaphore", @@ -38,7 +38,7 @@ cc_library( ":process_info_node", ":safe_process_map", "//score/launch_manager/daemon/src/common:identifier_hash", - "//score/launch_manager/daemon/src/configuration:configuration_manager", + "//score/launch_manager/daemon/src/configuration:configuration_adapter", "//score/launch_manager/daemon/src/control:control_client_channel", "//score/launch_manager/daemon/src/osal:semaphore", "//score/launch_manager/daemon/src/process_group_manager:iprocess", @@ -128,7 +128,7 @@ cc_library( "//score/launch_manager/daemon/src/common:log", "//score/launch_manager/daemon/src/common/concurrency:mpmc_concurrent_queue", "//score/launch_manager/daemon/src/common/concurrency:workerthread", - "//score/launch_manager/daemon/src/configuration:configuration_manager", + "//score/launch_manager/daemon/src/configuration:configuration_adapter", "//score/launch_manager/daemon/src/osal:ipc_comms", "//score/launch_manager/daemon/src/osal:semaphore", "//score/launch_manager/daemon/src/process_group_manager:process_group_manager_hdrs", diff --git a/score/launch_manager/daemon/src/process_group_manager/details/graph.cpp b/score/launch_manager/daemon/src/process_group_manager/details/graph.cpp index 41c01d6e0..7644a094b 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/graph.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/graph.cpp @@ -63,7 +63,7 @@ Graph::~Graph() void Graph::initProcessGroupNodes(IdentifierHash pg_name, uint32_t num_processes, uint32_t index) { pg_index_ = index; - off_state_ = pgm_->getConfigurationManager()->getNameOfOffState(pg_name); + off_state_ = pgm_->getConfigurationAdapter()->getNameOfOffState(pg_name); requested_state_.pg_state_name_ = off_state_; requested_state_.pg_name_ = pg_name; @@ -101,7 +101,7 @@ inline void Graph::createSuccessorLists(IdentifierHash pg_name) // If the other process has a dependency on this one, put it on the correct list auto node_index = node->getNodeIndex(); const DependencyList* dep_list = - pgm_->getConfigurationManager()->getOsProcessDependencies(pg_name, node_index).value_or(nullptr); + pgm_->getConfigurationAdapter()->getOsProcessDependencies(pg_name, node_index).value_or(nullptr); if (dep_list) { @@ -271,7 +271,7 @@ bool Graph::startTransition(ProcessGroupStateID pg_state) requested_state_.pg_state_name_ = pg_state.pg_state_name_; } const std::vector* process_index_list = - pgm_->getConfigurationManager()->getProcessIndexesList(requested_state_).value_or(nullptr); + pgm_->getConfigurationAdapter()->getProcessIndexesList(requested_state_).value_or(nullptr); if (nullptr != process_index_list) { diff --git a/score/launch_manager/daemon/src/process_group_manager/details/graph.hpp b/score/launch_manager/daemon/src/process_group_manager/details/graph.hpp index f1a8f2fcb..d39901ee3 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/graph.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/graph.hpp @@ -28,7 +28,7 @@ #include "score/mw/launch_manager/control/control_client_channel.hpp" #include "score/mw/launch_manager/process_group_manager/details/process_info_node.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" -#include "score/mw/launch_manager/configuration/configuration_manager.hpp" +#include "score/mw/launch_manager/configuration/configuration_adapter.hpp" namespace score { namespace lcm { diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp b/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp index 18980ac92..41142a966 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp @@ -40,7 +40,7 @@ void ProcessGroupManager::cancel() ProcessGroupManager::ProcessGroupManager(std::unique_ptr alive_monitor_thread, std::shared_ptr recovery_client, std::unique_ptr process_state_notifier) - : configuration_manager_(), + : configuration_adapter_(), process_interface_(), process_map_(nullptr), worker_threads_(nullptr), @@ -117,7 +117,7 @@ void ProcessGroupManager::deinitialize() { // ucm_polling_thread_.stopPolling(); alive_monitor_thread_->stop(); - configuration_manager_.deinitialize(); + configuration_adapter_.deinitialize(); process_groups_.clear(); worker_threads_.reset(); @@ -176,9 +176,9 @@ inline bool ProcessGroupManager::initializeProcessGroups() { bool success = false; - if (configuration_manager_.initialize()) + if (configuration_adapter_.initialize()) { - auto pg_list = configuration_manager_.getListOfProcessGroups().value_or(nullptr); + auto pg_list = configuration_adapter_.getListOfProcessGroups().value_or(nullptr); if (pg_list && !pg_list->empty()) { @@ -189,7 +189,7 @@ inline bool ProcessGroupManager::initializeProcessGroups() for (const auto& pg_name : *pg_list) { - uint32_t num_processes = configuration_manager_.getNumberOfOsProcesses(pg_name).value_or(0); + uint32_t num_processes = configuration_adapter_.getNumberOfOsProcesses(pg_name).value_or(0); if (static_cast(total_processes_) + num_processes <= static_cast(score::lcm::internal::ProcessLimits::kMaxProcesses)) @@ -242,13 +242,13 @@ inline void ProcessGroupManager::createProcessComponentsObjects() inline void ProcessGroupManager::initializeGraphNodes() { - auto pg_list = configuration_manager_.getListOfProcessGroups().value_or(nullptr); + auto pg_list = configuration_adapter_.getListOfProcessGroups().value_or(nullptr); for (size_t idx = 0U; idx < process_groups_.size(); ++idx) { process_groups_[idx]->initProcessGroupNodes( pg_list->at(idx), - configuration_manager_.getNumberOfOsProcesses(pg_list->at(idx)).value_or(0U), + configuration_adapter_.getNumberOfOsProcesses(pg_list->at(idx)).value_or(0U), static_cast(idx & 0xFFFFFFFFUL)); } @@ -292,7 +292,7 @@ inline bool ProcessGroupManager::startInitialTransition() LM_LOG_DEBUG() << "=============STARTING MAINPG STARTUP STATE============"; // Initial transition of machine process group - const ProcessGroupStateID* pg_startup_id = configuration_manager_.getMainPGStartupState().value_or(nullptr); + const ProcessGroupStateID* pg_startup_id = configuration_adapter_.getMainPGStartupState().value_or(nullptr); if (pg_startup_id) { @@ -534,7 +534,7 @@ inline void ProcessGroupManager::recoveryActionHandler() } const IdentifierHash old_state = pg->getProcessGroupState(); - const IdentifierHash recovery_state = configuration_manager_.getNameOfRecoveryState(pg->getProcessGroupName()); + const IdentifierHash recovery_state = configuration_adapter_.getNameOfRecoveryState(pg->getProcessGroupName()); const GraphState graph_state = pg->getState(); LM_LOG_DEBUG() << "recoveryActionHandler: Processing recovery request for PG " @@ -664,7 +664,7 @@ inline void ProcessGroupManager::processGetInitialMachineStateTransitionResult(C inline void ProcessGroupManager::processValidateFunctionStateID(ControlClientChannelP scc) { - if (configuration_manager_.getProcessIndexesList(scc->request().process_group_state_)) + if (configuration_adapter_.getProcessIndexesList(scc->request().process_group_state_)) { scc->request().request_or_response_ = ControlClientCode::kValidateProcessGroupStateSuccess; } @@ -713,7 +713,7 @@ inline void ProcessGroupManager::processGroupHandler(Graph& pg) ProcessGroupStateID recovery_state; recovery_state.pg_name_ = pg.getProcessGroupName(); - recovery_state.pg_state_name_ = configuration_manager_.getNameOfRecoveryState(recovery_state.pg_name_); + recovery_state.pg_state_name_ = configuration_adapter_.getNameOfRecoveryState(recovery_state.pg_name_); LM_LOG_WARN() << "Problem discovered in PG" << recovery_state.pg_name_ << "Activating Recovery state."; @@ -749,10 +749,10 @@ std::shared_ptr ProcessGroupManager::getProcessGroupByProcessId(const Ide for (auto& pg : process_groups_) { const IdentifierHash pg_name = pg->getProcessGroupName(); - const uint32_t count = configuration_manager_.getNumberOfOsProcesses(pg_name).value_or(0U); + const uint32_t count = configuration_adapter_.getNumberOfOsProcesses(pg_name).value_or(0U); for (uint32_t idx = 0U; idx < count; ++idx) { - const auto* proc = configuration_manager_.getOsProcessConfiguration(pg_name, idx).value_or(nullptr); + const auto* proc = configuration_adapter_.getOsProcessConfiguration(pg_name, idx).value_or(nullptr); if (proc != nullptr && proc->process_id_ == process_id) { return pg; @@ -787,9 +787,9 @@ osal::IProcess* ProcessGroupManager::getProcessInterface() return &process_interface_; } -ConfigurationManager* ProcessGroupManager::getConfigurationManager() +ConfigurationAdapter* ProcessGroupManager::getConfigurationAdapter() { - return &configuration_manager_; + return &configuration_adapter_; } std::shared_ptr ProcessGroupManager::getProcessMap() diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp index 2f2f94ac4..b04f1b3c7 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.cpp @@ -11,6 +11,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +#include + #include "process_info_node.hpp" #include "graph.hpp" #include "score/mw/launch_manager/process_group_manager/process_group_manager.hpp" @@ -41,7 +43,7 @@ void ProcessInfoNode::initNode(Graph* graph, uint32_t index) dependent_on_running_.clear(); dependent_on_terminating_.clear(); start_dependencies_ = 0U; - auto cfg_mgr = graph_->getProcessGroupManager()->getConfigurationManager(); + auto cfg_mgr = graph_->getProcessGroupManager()->getConfigurationAdapter(); config_ = cfg_mgr->getOsProcessConfiguration(pg, index).value_or(nullptr); if (config_) { diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.hpp b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.hpp index a04e6417b..c029b97a9 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_info_node.hpp @@ -15,7 +15,7 @@ #define _INCLUDED_PROCESSINFONODE_ #include -#include "score/mw/launch_manager/configuration/configuration_manager.hpp" +#include "score/mw/launch_manager/configuration/configuration_adapter.hpp" #include "score/mw/launch_manager/process_group_manager/details/safe_process_map.hpp" #include "score/mw/launch_manager/control/control_client_channel.hpp" diff --git a/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp b/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp index ca5b7a49a..b5acf365d 100644 --- a/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp @@ -20,7 +20,7 @@ #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/control/control_client_channel.hpp" -#include "score/mw/launch_manager/configuration/configuration_manager.hpp" +#include "score/mw/launch_manager/configuration/configuration_adapter.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" #include "score/mw/launch_manager/process_group_manager/details/graph.hpp" #include "score/mw/launch_manager/common/concurrency/mpmc_concurrent_queue.hpp" @@ -42,10 +42,10 @@ namespace score::lcm::internal /// coherent way. Through a Process Group, Launch Manager will control the life cycle of Operating System (OS) /// processes. They will be started and stopped when State Management (SM) request so and they will be started and /// stopped in a way, that is described by integrator through configuration. When SM request PG change, -/// ProcessGroupManager will use ConfigurationManager to figure out what processes shall be started, or stopped, as well +/// ProcessGroupManager will use ConfigurationAdapter to figure out what processes shall be started, or stopped, as well /// as their startup configuration. Then ProcessGroupManager will use Operating System Abstraction Layer (OSAL) to /// start, or stop, processes as per configuration. Some of the responsibilities of ProcessGroupManager include: -/// Interaction with ConfigurationManager to ensure that, the list of processes that are running on Machine, is as +/// Interaction with ConfigurationAdapter to ensure that, the list of processes that are running on Machine, is as /// configured by integrator. Interaction with OSAL to start and stop processes. Interaction with OSAL to discover /// when processes terminated in an unexpected way. Fulfilling PG State transitions requests from SM, as well as /// informing SM about unexpected problems (for example process crashes). @@ -69,7 +69,7 @@ class ProcessGroupManager final std::unique_ptr process_state_notifier); /// @brief Initializes the process group manager. - /// Loads the flat configuration through ConfigurationManager. + /// Loads the flat configuration through ConfigurationAdapter. /// Sets up a signal handler for SIGINT and SIGTERM so that the main loop of /// the run() method will be exited in the event of those signals /// Creates the process map, worker threads and worker job queues. @@ -122,8 +122,8 @@ class ProcessGroupManager final osal::IProcess* getProcessInterface(); /// @brief Gets the configuration manager. - /// @return Pointer to the ConfigurationManager object. - ConfigurationManager* getConfigurationManager(); + /// @return Pointer to the ConfigurationAdapter object. + ConfigurationAdapter* getConfigurationAdapter(); /// @brief Gets the process map. /// @return Shared pointer to the SafeProcessMap object. @@ -271,8 +271,8 @@ class ProcessGroupManager final /// @brief Initializes the Control Client handler. inline bool initializeControlClientHandler(); - /// @brief The ConfigurationManager object associated with the ProcessGroupManager. - ConfigurationManager configuration_manager_; + /// @brief The ConfigurationAdapter object associated with the ProcessGroupManager. + ConfigurationAdapter configuration_adapter_; /// @brief The process interface object associated with the ProcessGroupManager. osal::IProcess process_interface_; diff --git a/scripts/config_mapping/config.bzl b/scripts/config_mapping/config.bzl index e2a22293e..dbae347a6 100644 --- a/scripts/config_mapping/config.bzl +++ b/scripts/config_mapping/config.bzl @@ -4,8 +4,6 @@ def _launch_manager_config_impl(ctx): script = ctx.executable.script json_out_dir = ctx.attr.json_out_dir - # Run the mapping script to generate the json files in the old configuration format - # We need to declare an output directory, because we do not know upfront the name of the generated files nor the number of files. gen_dir_json = ctx.actions.declare_directory(json_out_dir) ctx.actions.run( inputs = [config, schema], @@ -26,49 +24,22 @@ def _launch_manager_config_impl(ctx): flatbuffer_out_dir = ctx.attr.flatbuffer_out_dir flatc = ctx.executable.flatc lm_schema = ctx.file.lm_schema - hm_schema = ctx.file.hm_schema - hmcore_schema = ctx.file.hmcore_schema - # We compile each of them via flatbuffer. - # Based on the name of each generated file, we select the corresponding schema. gen_dir_flatbuffer = ctx.actions.declare_directory(flatbuffer_out_dir) - ctx.actions.run_shell( - inputs = [gen_dir_json, lm_schema, hm_schema, hmcore_schema], + ctx.actions.run( + inputs = [gen_dir_json, lm_schema], outputs = [gen_dir_flatbuffer], tools = [flatc], - command = """ - mkdir -p {gen_dir_flatbuffer} - # Process each file from generated directory - for file in {gen_dir_json}/*; do - if [ -f "$file" ]; then - filename=$(basename "$file") - - if [[ "$filename" == "lm_"* ]]; then - schema={lm_schema} - elif [[ "$filename" == "hmcore"* ]]; then - schema={hmcore_schema} - elif [[ "$filename" == "hm_"* ]]; then - schema={hm_schema} - else - echo "Unknown file type for $filename, skipping." - continue - fi - - # Process with flatc - {flatc} -b -o {gen_dir_flatbuffer} "$schema" "$file" - fi - done - """.format( - gen_dir_flatbuffer = gen_dir_flatbuffer.path, - gen_dir_json = gen_dir_json.path, - lm_schema = lm_schema.path, - hmcore_schema = hmcore_schema.path, - hm_schema = hm_schema.path, - flatc = flatc.path, - ), - arguments = [], + executable = flatc, mnemonic = "LaunchManagerFlatbufferConfigGeneration", - progress_message = "compiling generated Launch Manager configs in {} to flatbuffer files in {}".format(gen_dir_json.short_path, gen_dir_flatbuffer.short_path), + progress_message = "compiling Launch Manager config in {} to flatbuffer in {}".format(gen_dir_json.short_path, gen_dir_flatbuffer.short_path), + arguments = [ + "-b", + "-o", + gen_dir_flatbuffer.path, + lm_schema.path, + gen_dir_json.path + "/launch_manager_config.json", + ], ) rf = ctx.runfiles( @@ -115,18 +86,8 @@ launch_manager_config = rule( ), "lm_schema": attr.label( allow_single_file = [".fbs"], - default = Label("//score/launch_manager/daemon/src/configuration:lm_flatcfg_fbs"), + default = Label("//score/launch_manager/daemon/src/configuration:new_lm_flatcfg_fbs"), doc = "Launch Manager fbs file to use", ), - "hm_schema": attr.label( - allow_single_file = [".fbs"], - default = Label("//score/launch_manager/daemon/src/alive_monitor:am_flatcfg_fbs"), - doc = "HealthMonitor fbs file to use", - ), - "hmcore_schema": attr.label( - allow_single_file = [".fbs"], - default = Label("//score/launch_manager/daemon/src/alive_monitor:am_core_flatcfg_fbs"), - doc = "HealthMonitor core fbs file to use", - ), }, ) diff --git a/scripts/config_mapping/integration_tests.py b/scripts/config_mapping/integration_tests.py index c9aabdce7..31a250a0b 100644 --- a/scripts/config_mapping/integration_tests.py +++ b/scripts/config_mapping/integration_tests.py @@ -135,7 +135,7 @@ def test_health_config_mapping(): test_name = "health_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, exclude_files=["lm_demo.json"]) + run(input_file, test_name) def test_empty_health_config_mapping(): @@ -145,7 +145,7 @@ def test_empty_health_config_mapping(): test_name = "empty_health_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, exclude_files=["lm_demo.json"]) + run(input_file, test_name) def test_launch_config_mapping(): @@ -158,7 +158,7 @@ def test_launch_config_mapping(): test_name = "lm_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, compare_files_only=["lm_demo.json"]) + run(input_file, test_name, compare_files_only=["launch_manager_config.json"]) def test_empty_launch_config_mapping(): @@ -168,7 +168,7 @@ def test_empty_launch_config_mapping(): test_name = "empty_lm_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, compare_files_only=["lm_demo.json"]) + run(input_file, test_name, compare_files_only=["launch_manager_config.json"]) def test_custom_validation_failures(): diff --git a/scripts/config_mapping/lifecycle_config.py b/scripts/config_mapping/lifecycle_config.py index 29255bb42..545291f16 100644 --- a/scripts/config_mapping/lifecycle_config.py +++ b/scripts/config_mapping/lifecycle_config.py @@ -74,9 +74,10 @@ def report_error(message): print(f"Error: {message}", file=sys.stderr) -# There are various dictionaries in the config where only a single entry is allowed. -# We do not want to merge the defaults with the user specified values for these dictionaries. -not_merging_dicts = ["ready_recovery_action", "recovery_action"] +# These dictionaries select a single action type (e.g. "restart" vs "switch_run_target"). +# When merging, we preserve the user's chosen action type rather than merging across types, +# but we still deep-merge fields within the chosen action type to fill in missing defaults. +_action_selection_dicts = ["ready_recovery_action", "recovery_action"] def load_json_file(file_path: str) -> Dict[str, Any]: @@ -85,19 +86,10 @@ def load_json_file(file_path: str) -> Dict[str, Any]: return json.load(file) -def get_recovery_process_group_state(config): - # Existence has already been validated in the custom_validations function - return "MainPG/fallback_run_target" - - -def sec_to_ms(sec: float) -> int: - return int(sec * 1000) - - def preprocess_defaults(global_defaults, config): """ - This function takes the input configuration and fills in any missing fields with default values. - The resulting file with have no "defaults" entry anymore, but looks like if the user had specified all the fields explicitly. + Takes the input configuration and fills in any missing fields with default values. + The resulting config has no "defaults" entry; all fields are explicit. """ def dict_merge(dict_a, dict_b): @@ -108,9 +100,22 @@ def dict_merge_recursive(dict_a, dict_b): and isinstance(dict_a[key], dict) and isinstance(value, dict) ): - # For certain dictionaries, we do not want to merge the defaults with the user specified values - if key in not_merging_dicts: - dict_a[key] = value + if key in _action_selection_dicts: + # Replace the action-type selection (don't merge across types), + # but still deep-merge fields within the chosen action type. + new_val = {} + for action_key, action_val in value.items(): + if ( + action_key in dict_a[key] + and isinstance(dict_a[key][action_key], dict) + and isinstance(action_val, dict) + ): + new_val[action_key] = dict_merge( + dict_a[key][action_key], action_val + ) + else: + new_val[action_key] = action_val + dict_a[key] = new_val else: dict_a[key] = dict_merge(dict_a[key], value) elif key not in dict_a: @@ -135,8 +140,7 @@ def dict_merge_recursive(dict_a, dict_b): new_config = {} new_config["components"] = {} - components = config.get("components", {}) - for component_name, component_config in components.items(): + for component_name, component_config in config.get("components", {}).items(): # print("Processing component:", component_name) new_config["components"][component_name] = {} new_config["components"][component_name]["description"] = component_config.get( @@ -145,18 +149,13 @@ def dict_merge_recursive(dict_a, dict_b): # Here we start with the merged defaults, then apply the component config on top, so that any fields specified in the component config will override the defaults. new_config["components"][component_name]["component_properties"] = dict_merge( merged_defaults["component_properties"], - component_config.get("component_properties"), + component_config.get("component_properties", {}), ) new_config["components"][component_name]["deployment_config"] = dict_merge( merged_defaults["deployment_config"], component_config.get("deployment_config", {}), ) - # Special case: - # If the defaults specify alive_supervision for component, but the component config sets the type to anything other than "SUPERVISED", then we should not apply the - # alive_supervision defaults to that component, since it doesn't make sense to have alive_supervision from the defaults. - # TODO - new_config["run_targets"] = {} for run_target, run_target_config in config.get("run_targets", {}).items(): new_config["run_targets"][run_target] = dict_merge( @@ -170,387 +169,15 @@ def dict_merge_recursive(dict_a, dict_b): merged_defaults["watchdog"], config.get("watchdog", {}) ) - for key in ("initial_run_target", "fallback_run_target"): - if key in config: - new_config[key] = config[key] - - # print(json.dumps(new_config, indent=4)) - - return new_config - - -def is_supervised(application_type): - return ( - application_type == "State_Manager" - or application_type == "Reporting_And_Supervised" - ) - - -def gen_health_monitor_config(output_dir, config): - """ - This function generates the health monitor configuration file based on the input configuration. - Input: - output_dir: The directory where the generated files should be saved - config: The preprocessed configuration in the new format, with all defaults applied - - Output: - - A file named "hm_demo.json" containing the health monitor daemon configuration - - A optional file named "hmcore.json" containing the watchdog configuration - - For each supervised process, a file named "_.json" - """ - - def get_process_type(application_type): - if application_type == "State_Manager": - return "STM_PROCESS" - else: - return "REGULAR_PROCESS" - - HM_SCHEMA_VERSION_MAJOR = 8 - HM_SCHEMA_VERSION_MINOR = 1 - hm_config = {} - hm_config["versionMajor"] = HM_SCHEMA_VERSION_MAJOR - hm_config["versionMinor"] = HM_SCHEMA_VERSION_MINOR - hm_config["process"] = [] - hm_config["hmMonitorInterface"] = [] - hm_config["hmSupervisionCheckpoint"] = [] - hm_config["hmAliveSupervision"] = [] - index = 0 - for component_name, component_config in config["components"].items(): - if is_supervised( - component_config["component_properties"]["application_profile"][ - "application_type" - ] - ): - process = {} - process["index"] = index - process["shortName"] = component_name - process["identifier"] = component_name - process["processType"] = get_process_type( - component_config["component_properties"]["application_profile"][ - "application_type" - ] - ) - hm_config["process"].append(process) - - hmMonitorIf = {} - hmMonitorIf["instanceSpecifier"] = component_name - hmMonitorIf["processShortName"] = component_name - hmMonitorIf["portPrototype"] = "DefaultPort" - hmMonitorIf["interfacePath"] = "lifecycle_health_" + component_name - hmMonitorIf["refProcessIndex"] = index - hmMonitorIf["permittedUid"] = component_config["deployment_config"][ - "sandbox" - ]["uid"] - hm_config["hmMonitorInterface"].append(hmMonitorIf) - - checkpoint = {} - checkpoint["shortName"] = component_name + "_checkpoint" - checkpoint["checkpointId"] = 1 - checkpoint["refInterfaceIndex"] = index - hm_config["hmSupervisionCheckpoint"].append(checkpoint) - - alive_supervision = {} - alive_supervision["ruleContextKey"] = component_name + "_alive_supervision" - alive_supervision["refCheckPointIndex"] = index - alive_supervision["aliveReferenceCycle"] = sec_to_ms( - component_config["component_properties"]["application_profile"][ - "alive_supervision" - ]["reporting_cycle"] - ) - alive_supervision["minAliveIndications"] = component_config[ - "component_properties" - ]["application_profile"]["alive_supervision"]["min_indications"] - alive_supervision["maxAliveIndications"] = component_config[ - "component_properties" - ]["application_profile"]["alive_supervision"]["max_indications"] - alive_supervision["isMinCheckDisabled"] = ( - alive_supervision["minAliveIndications"] == 0 - ) - alive_supervision["isMaxCheckDisabled"] = ( - alive_supervision["maxAliveIndications"] == 0 - ) - alive_supervision["failedSupervisionCyclesTolerance"] = component_config[ - "component_properties" - ]["application_profile"]["alive_supervision"]["failed_cycles_tolerance"] - alive_supervision["refProcessIndex"] = index - hm_config["hmAliveSupervision"].append(alive_supervision) - - index += 1 - - with open(f"{output_dir}/hm_demo.json", "w") as hm_file: - json.dump(hm_config, hm_file, indent=4) - - HM_CORE_SCHEMA_VERSION_MAJOR = 3 - HM_CORE_SCHEMA_VERSION_MINOR = 0 - hmcore_config = {} - hmcore_config["versionMajor"] = HM_CORE_SCHEMA_VERSION_MAJOR - hmcore_config["versionMinor"] = HM_CORE_SCHEMA_VERSION_MINOR - hmcore_config["watchdogs"] = [] - hmcore_config["config"] = [ - { - "periodicity": sec_to_ms( - config.get("alive_supervision", {}).get("evaluation_cycle", 0.01) - ) - } - ] - - if watchdog_config := config.get("watchdog", {}): - watchdog = {} - watchdog["shortName"] = "watchdog" - watchdog["deviceFilePath"] = watchdog_config["device_file_path"] - watchdog["maxTimeout"] = sec_to_ms(watchdog_config["max_timeout"]) - watchdog["deactivateOnShutdown"] = watchdog_config["deactivate_on_shutdown"] - watchdog["hasValueDeactivateOnShutdown"] = True - watchdog["requireMagicClose"] = watchdog_config["require_magic_close"] - watchdog["hasValueRequireMagicClose"] = True - hmcore_config["watchdogs"].append(watchdog) - - with open(f"{output_dir}/hmcore.json", "w") as hm_file: - json.dump(hmcore_config, hm_file, indent=4) - - -def gen_launch_manager_config(output_dir, config): - """ - This function generates the launch manager configuration file based on the input configuration. - Input: - output_dir: The directory where the generated files should be saved - config: The preprocessed configuration in the new format, with all defaults applied - - Output: - - A file named "lm_demo.json" containing the launch manager configuration - """ - - """ - Recursively get all components on which the run target depends - """ + if "initial_run_target" in config: + new_config["initial_run_target"] = config["initial_run_target"] - def format_dependency_path(path, cycle_target): - """Format a dependency resolution path for display, highlighting the cycle.""" - return " -> ".join(path + [cycle_target]) - - def get_process_dependencies( - run_target, ancestors_run_targets=None, ancestors_components=None - ): - """ - Resolve all component dependencies for the given run target. - - ancestors_run_targets and ancestors_components track the current - recursion path to detect cyclic dependencies without rejecting - legitimate diamond-shaped dependency trees. - """ - if ancestors_run_targets is None: - ancestors_run_targets = [] - if ancestors_components is None: - ancestors_components = [] - - out = [] - if "depends_on" not in run_target: - return out - - for dependency_name in run_target["depends_on"]: - if dependency_name in config["components"]: - if dependency_name in ancestors_components: - path = format_dependency_path(ancestors_components, dependency_name) - raise ValueError( - f"Cyclic dependency detected: component '{dependency_name}' " - f"has already been visited.\n Path: {path}" - ) - ancestors_components.append(dependency_name) - out.append(dependency_name) - - component_props = config["components"][dependency_name][ - "component_properties" - ] - if "depends_on" in component_props: - # All dependencies must be components, since components can't depend on run targets - for dep in component_props["depends_on"]: - if dep not in config["components"]: - raise ValueError( - f"Component '{dependency_name}' depends on unknown component '{dep}'." - ) - if dep in ancestors_components: - path = format_dependency_path(ancestors_components, dep) - raise ValueError( - f"Cyclic dependency detected: component '{dependency_name}' " - f"depends on already visited component '{dep}'.\n Path: {path}" - ) - ancestors_components.append(dep) - out.append(dep) - out += get_process_dependencies( - config["components"][dep]["component_properties"], - ancestors_run_targets=ancestors_run_targets, - ancestors_components=ancestors_components, - ) - ancestors_components.pop() - - ancestors_components.pop() - else: - # If the dependency is not a component, it must be a run target - if dependency_name not in config["run_targets"]: - raise ValueError( - f"Run target depends on unknown run target or component '{dependency_name}'." - ) - if dependency_name in ancestors_run_targets: - path = format_dependency_path( - ancestors_run_targets, dependency_name - ) - raise ValueError( - f"Cyclic dependency detected: run target '{dependency_name}' " - f"has already been visited.\n Path: {path}" - ) - ancestors_run_targets.append(dependency_name) - out += get_process_dependencies( - config["run_targets"][dependency_name], - ancestors_run_targets=ancestors_run_targets, - ancestors_components=ancestors_components, - ) - ancestors_run_targets.pop() - return list(set(out)) # Remove duplicates - - def get_terminating_behavior(component_config): - if component_config["component_properties"]["application_profile"][ - "is_self_terminating" - ]: - return "ProcessIsSelfTerminating" - else: - return "ProcessIsNotSelfTerminating" - - lm_config = {} - lm_config["versionMajor"] = 7 - lm_config["versionMinor"] = 0 - lm_config["Process"] = [] - lm_config["ModeGroup"] = [ - { - "identifier": "MainPG", - "initialMode_name": "not-used", - "recoveryMode_name": get_recovery_process_group_state(config), - "modeDeclaration": [], - } - ] - - process_group_states = {} - - # For each component, store which run targets depends on it - for pgstate, values in config["run_targets"].items(): - state_name = "MainPG/" + pgstate - lm_config["ModeGroup"][0]["modeDeclaration"].append({"identifier": state_name}) - components = get_process_dependencies(values) - for component in components: - if component not in process_group_states: - process_group_states[component] = [] - process_group_states[component].append(state_name) - - if fallback := config.get("fallback_run_target", {}): - lm_config["ModeGroup"][0]["modeDeclaration"].append( - {"identifier": "MainPG/fallback_run_target"} - ) - fallback_components = get_process_dependencies(fallback) - for component in fallback_components: - if component not in process_group_states: - process_group_states[component] = [] - process_group_states[component].append("MainPG/fallback_run_target") - - for component_name, component_config in config["components"].items(): - process = {} - process["identifier"] = component_name - process["path"] = ( - f"{component_config['deployment_config']['bin_dir']}/{component_config['component_properties']['binary_name']}" - ) - process["uid"] = component_config["deployment_config"]["sandbox"]["uid"] - process["gid"] = component_config["deployment_config"]["sandbox"]["gid"] - process["sgids"] = [ - {"sgid": sgid} - for sgid in component_config["deployment_config"]["sandbox"][ - "supplementary_group_ids" - ] - ] - process["securityPolicyDetails"] = component_config["deployment_config"][ - "sandbox" - ]["security_policy"] - process["numberOfRestartAttempts"] = component_config["deployment_config"][ - "ready_recovery_action" - ]["restart"]["number_of_attempts"] - - match component_config["component_properties"]["application_profile"][ - "application_type" - ]: - case "Native": - process["executable_reportingBehavior"] = "DoesNotReportExecutionState" - case "State_Manager": - process["executable_reportingBehavior"] = "ReportsExecutionState" - process["functionClusterAffiliation"] = "STATE_MANAGEMENT" - case "Reporting" | "Reporting_And_Supervised": - process["executable_reportingBehavior"] = "ReportsExecutionState" - - process["startupConfig"] = [{}] - process["startupConfig"][0]["executionError"] = "1" - process["startupConfig"][0]["identifier"] = f"{component_name}_startup_config" - process["startupConfig"][0]["enterTimeoutValue"] = sec_to_ms( - component_config["deployment_config"]["ready_timeout"] + if "fallback_run_target" in config: + new_config["fallback_run_target"] = dict_merge( + merged_defaults["run_target"], config["fallback_run_target"] ) - process["startupConfig"][0]["exitTimeoutValue"] = sec_to_ms( - component_config["deployment_config"]["shutdown_timeout"] - ) - process["startupConfig"][0]["schedulingPolicy"] = component_config[ - "deployment_config" - ]["sandbox"]["scheduling_policy"] - process["startupConfig"][0]["schedulingPriority"] = str( - component_config["deployment_config"]["sandbox"]["scheduling_priority"] - ) - process["startupConfig"][0]["terminationBehavior"] = get_terminating_behavior( - component_config - ) - process["startupConfig"][0]["processGroupStateDependency"] = [] - process["startupConfig"][0]["environmentVariable"] = [] - for env_var, value in ( - component_config["deployment_config"] - .get("environmental_variables", {}) - .items() - ): - process["startupConfig"][0]["environmentVariable"].append( - {"key": env_var, "value": value} - ) - application_type = component_config["component_properties"][ - "application_profile" - ]["application_type"] - if is_supervised(application_type): - process["startupConfig"][0]["environmentVariable"].append( - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_" + component_name, - } - ) - if arguments := component_config["component_properties"].get( - "process_arguments", [] - ): - arguments = [{"argument": arg} for arg in arguments] - process["startupConfig"][0]["processArgument"] = arguments - - if component_name in process_group_states: - for pgstate in process_group_states[component_name]: - process["startupConfig"][0]["processGroupStateDependency"].append( - {"stateMachine_name": "MainPG", "stateName": pgstate} - ) - - lm_config["Process"].append(process) - - # Execution dependencies. Assumption: Components can never depend on run targets - for process in lm_config["Process"]: - process["startupConfig"][0]["executionDependency"] = [] - for dependency in config["components"][process["identifier"]][ - "component_properties" - ].get("depends_on", []): - dep_entry = config["components"][dependency] - ready_condition = dep_entry["component_properties"]["ready_condition"][ - "process_state" - ] - process["startupConfig"][0]["executionDependency"].append( - {"stateName": ready_condition, "targetProcess_identifier": dependency} - ) - - with open(f"{output_dir}/lm_demo.json", "w") as lm_file: - json.dump(lm_config, lm_file, indent=4) + return new_config def custom_validations(config): @@ -574,14 +201,18 @@ def custom_validations(config): ) success = False - # Check that for any switch_run_target recovery action, the run_target is set to "fallback_run_target" - for _, run_target in config["run_targets"].items(): - recovery_target_name = ( - run_target.get("recovery_action", {}) - .get("switch_run_target", {}) - .get("run_target", "fallback_run_target") - ) - if recovery_target_name != "fallback_run_target": + for run_target_name, run_target in config["run_targets"].items(): + recovery_action = run_target.get("recovery_action", {}) + if "switch_run_target" not in recovery_action: + report_error( + f'RunTarget "{run_target_name}" has an unsupported recovery_action type. ' + "Only switch_run_target is supported for run targets." + ) + success = False + elif ( + recovery_action["switch_run_target"].get("run_target") + != "fallback_run_target" + ): report_error( 'For any switch_run_target recovery action, the recovery RunTarget must be set to "fallback_run_target".' ) @@ -593,6 +224,13 @@ def custom_validations(config): ) success = False + watchdog = config.get("watchdog") + if watchdog: + missing = [f for f in _WATCHDOG_REQUIRED if f not in watchdog] + if missing: + report_error(f"watchdog config is missing required fields: {missing}") + success = False + return success @@ -632,6 +270,183 @@ def schema_validation(json_input, schema, config_path=None, schema_path=None): SCHEMA_VALIDATION_FAILURE = 2 CUSTOM_VALIDATION_FAILURE = 3 +OUTPUT_FILENAME = "launch_manager_config.json" + +_WATCHDOG_REQUIRED = ( + "device_file_path", + "max_timeout", + "deactivate_on_shutdown", + "require_magic_close", +) + +SCHED_POLICY_MAP = { + "SCHED_OTHER": "OTHER", + "SCHED_FIFO": "FIFO", + "SCHED_RR": "RR", +} + + +def is_supervised(application_type): + return application_type in ("State_Manager", "Reporting_And_Supervised") + + +def _map_sandbox(sandbox): + result = { + "uid": sandbox["uid"], + "gid": sandbox["gid"], + "supplementary_group_ids": sandbox.get("supplementary_group_ids", []), + "security_policy": sandbox.get("security_policy", ""), + "scheduling_policy": SCHED_POLICY_MAP.get( + sandbox["scheduling_policy"], sandbox["scheduling_policy"] + ), + "scheduling_priority": sandbox["scheduling_priority"], + } + if "max_memory_usage" in sandbox: + result["max_memory_usage"] = sandbox["max_memory_usage"] + if "max_cpu_usage" in sandbox: + result["max_cpu_usage"] = sandbox["max_cpu_usage"] + return result + + +def _map_deployment_config(deployment): + result = { + "ready_timeout": deployment["ready_timeout"], + "shutdown_timeout": deployment["shutdown_timeout"], + "bin_dir": deployment["bin_dir"], + "working_dir": deployment["working_dir"], + "sandbox": _map_sandbox(deployment["sandbox"]), + } + + env_vars = deployment.get("environmental_variables", {}) + if env_vars: + result["environmental_variables"] = [ + {"key": k, "value": v} for k, v in env_vars.items() + ] + + ready_recovery = deployment.get("ready_recovery_action", {}) + if restart := ready_recovery.get("restart"): + result["ready_recovery_action"] = { + "number_of_attempts": restart["number_of_attempts"], + "delay_before_restart": restart["delay_before_restart"], + } + + recovery = deployment.get("recovery_action", {}) + if switch := recovery.get("switch_run_target"): + result["recovery_action"] = {"run_target": switch["run_target"]} + + return result + + +def _map_application_profile(profile): + result = { + "application_type": profile["application_type"], + "is_self_terminating": profile["is_self_terminating"], + } + if is_supervised(profile["application_type"]): + if alive := profile.get("alive_supervision"): + result["alive_supervision"] = { + "reporting_cycle": alive["reporting_cycle"], + "failed_cycles_tolerance": alive["failed_cycles_tolerance"], + "min_indications": alive["min_indications"], + "max_indications": alive["max_indications"], + } + return result + + +def _map_component_properties(props): + result = { + "binary_name": props["binary_name"], + "application_profile": _map_application_profile(props["application_profile"]), + } + if (depends_on := props.get("depends_on")) is not None: + result["depends_on"] = depends_on + if (process_arguments := props.get("process_arguments")) is not None: + result["process_arguments"] = process_arguments + if ready_condition := props.get("ready_condition"): + result["ready_condition"] = {"process_state": ready_condition["process_state"]} + return result + + +def _copy_run_target_optional_fields(source, dest): + if description := source.get("description", ""): + dest["description"] = description + if depends_on := source.get("depends_on", []): + dest["depends_on"] = depends_on + + +def _map_run_target(name, run_target): + switch = run_target.get("recovery_action", {}).get("switch_run_target") + if switch is None: + raise ValueError( + f'RunTarget "{name}" recovery_action must use switch_run_target.' + ) + result = { + "name": name, + "transition_timeout": run_target["transition_timeout"], + "recovery_action": {"run_target": switch["run_target"]}, + } + _copy_run_target_optional_fields(run_target, result) + return result + + +def _map_fallback_run_target(fallback): + result = { + "transition_timeout": fallback["transition_timeout"], + } + _copy_run_target_optional_fields(fallback, result) + return result + + +def gen_config(output_dir, config): + """ + Generate a single launch_manager_config.json matching new_lm_flatcfg.fbs. + + Input: + output_dir: Directory where the file is written + config: Preprocessed configuration with all defaults applied + Output: + A file named "launch_manager_config.json" + """ + output = {} + + if "schema_version" in config: + output["schema_version"] = config["schema_version"] + + output["components"] = [ + { + "name": name, + "description": component.get("description", ""), + "component_properties": _map_component_properties( + component["component_properties"] + ), + "deployment_config": _map_deployment_config(component["deployment_config"]), + } + for name, component in config["components"].items() + ] + + output["run_targets"] = [ + _map_run_target(name, rt) for name, rt in config["run_targets"].items() + ] + + output["initial_run_target"] = config["initial_run_target"] + + output["fallback_run_target"] = _map_fallback_run_target( + config["fallback_run_target"] + ) + + output["alive_supervision"] = { + "evaluation_cycle": config["alive_supervision"]["evaluation_cycle"] + } + + if watchdog := config.get("watchdog"): + missing = [f for f in _WATCHDOG_REQUIRED if f not in watchdog] + if missing: + raise ValueError(f"watchdog config is missing required fields: {missing}") + output["watchdog"] = {f: watchdog[f] for f in _WATCHDOG_REQUIRED} + + with open(f"{output_dir}/{OUTPUT_FILENAME}", "w") as f: + json.dump(output, f, indent=4) + def main(): parser = argparse.ArgumentParser() @@ -658,7 +473,8 @@ def main(): # User asked not explicitly for validation, but the dependency is not installed, we should print a warning and continue without validation if not check_validation_dependency(): print( - 'lifecycle_config.py:jsonschema library is not installed. Please install it with "pip install jsonschema" to enable schema validation.' + "lifecycle_config.py: jsonschema library is not installed. " + 'Please install it with "pip install jsonschema" to enable schema validation.' ) print("Schema validation will be skipped.") else: @@ -680,12 +496,13 @@ def main(): ) preprocessed_config = preprocess_defaults(score_defaults, input_config) + if "schema_version" in input_config: + preprocessed_config["schema_version"] = input_config["schema_version"] if not custom_validations(preprocessed_config): exit(CUSTOM_VALIDATION_FAILURE) try: - gen_health_monitor_config(args.output_dir, preprocessed_config) - gen_launch_manager_config(args.output_dir, preprocessed_config) + gen_config(args.output_dir, preprocessed_config) except ValueError as e: print(f"Error during configuration generation: {e}", file=sys.stderr) exit(CUSTOM_VALIDATION_FAILURE) diff --git a/scripts/config_mapping/tests/basic_test/expected_output/hm_demo.json b/scripts/config_mapping/tests/basic_test/expected_output/hm_demo.json deleted file mode 100644 index 787033b37..000000000 --- a/scripts/config_mapping/tests/basic_test/expected_output/hm_demo.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "versionMajor": 8, - "versionMinor": 1, - "process": [ - { - "index": 0, - "shortName": "someip-daemon", - "identifier": "someip-daemon", - "processType": "REGULAR_PROCESS" - }, - { - "index": 1, - "shortName": "test_app1", - "identifier": "test_app1", - "processType": "REGULAR_PROCESS" - }, - { - "index": 2, - "shortName": "state_manager", - "identifier": "state_manager", - "processType": "STM_PROCESS" - } - ], - "hmMonitorInterface": [ - { - "instanceSpecifier": "someip-daemon", - "processShortName": "someip-daemon", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_someip-daemon", - "refProcessIndex": 0, - "permittedUid": 1000 - }, - { - "instanceSpecifier": "test_app1", - "processShortName": "test_app1", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_test_app1", - "refProcessIndex": 1, - "permittedUid": 1000 - }, - { - "instanceSpecifier": "state_manager", - "processShortName": "state_manager", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_state_manager", - "refProcessIndex": 2, - "permittedUid": 1000 - } - ], - "hmSupervisionCheckpoint": [ - { - "shortName": "someip-daemon_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 0 - }, - { - "shortName": "test_app1_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 1 - }, - { - "shortName": "state_manager_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 2 - } - ], - "hmAliveSupervision": [ - { - "ruleContextKey": "someip-daemon_alive_supervision", - "refCheckPointIndex": 0, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 0 - }, - { - "ruleContextKey": "test_app1_alive_supervision", - "refCheckPointIndex": 1, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 1 - }, - { - "ruleContextKey": "state_manager_alive_supervision", - "refCheckPointIndex": 2, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 2 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/basic_test/expected_output/hmcore.json b/scripts/config_mapping/tests/basic_test/expected_output/hmcore.json deleted file mode 100644 index f06adf403..000000000 --- a/scripts/config_mapping/tests/basic_test/expected_output/hmcore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "versionMajor": 3, - "versionMinor": 0, - "watchdogs": [ - { - "shortName": "watchdog", - "deviceFilePath": "/dev/watchdog", - "maxTimeout": 2000, - "deactivateOnShutdown": true, - "hasValueDeactivateOnShutdown": true, - "requireMagicClose": false, - "hasValueRequireMagicClose": true - } - ], - "config": [ - { - "periodicity": 500 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json new file mode 100644 index 000000000..886e85ce5 --- /dev/null +++ b/scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json @@ -0,0 +1,373 @@ +{ + "schema_version": 1, + "components": [ + { + "name": "setup_filesystem_sh", + "description": "Script to mount partitions at the right directories", + "component_properties": { + "binary_name": "bin/setup_filesystem.sh", + "application_profile": { + "application_type": "Native", + "is_self_terminating": true + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b" + ], + "ready_condition": { + "process_state": "Terminated" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "Off" + } + } + }, + { + "name": "dlt-daemon", + "description": "Logging application", + "component_properties": { + "binary_name": "dltd", + "application_profile": { + "application_type": "Native", + "is_self_terminating": false + }, + "depends_on": [ + "setup_filesystem_sh" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/dlt-daemon", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "Off" + } + } + }, + { + "name": "someip-daemon", + "description": "SOME/IP application", + "component_properties": { + "binary_name": "someipd", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/someip", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "Off" + } + } + }, + { + "name": "test_app1", + "description": "Simple test application", + "component_properties": { + "binary_name": "test_app1", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [ + "dlt-daemon", + "someip-daemon" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/test_app1", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "Off" + } + } + }, + { + "name": "state_manager", + "description": "Application that manages life cycle of the ECU", + "component_properties": { + "binary_name": "sm", + "application_profile": { + "application_type": "State_Manager", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [ + "setup_filesystem_sh" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/state_manager", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "Off" + } + } + } + ], + "run_targets": [ + { + "name": "Startup", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Minimal functionality of the system", + "depends_on": [ + "state_manager" + ] + }, + { + "name": "Full", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Everything running", + "depends_on": [ + "test_app1", + "Startup" + ] + } + ], + "initial_run_target": "Startup", + "fallback_run_target": { + "transition_timeout": 1.5, + "description": "Switching off everything" + }, + "alive_supervision": { + "evaluation_cycle": 0.5 + }, + "watchdog": { + "device_file_path": "/dev/watchdog", + "max_timeout": 2, + "deactivate_on_shutdown": true, + "require_magic_close": false + } +} \ No newline at end of file diff --git a/scripts/config_mapping/tests/basic_test/expected_output/lm_demo.json b/scripts/config_mapping/tests/basic_test/expected_output/lm_demo.json deleted file mode 100644 index 71ee9209a..000000000 --- a/scripts/config_mapping/tests/basic_test/expected_output/lm_demo.json +++ /dev/null @@ -1,376 +0,0 @@ -{ - "versionMajor": 7, - "versionMinor": 0, - "Process": [ - { - "identifier": "setup_filesystem_sh", - "path": "/opt/scripts/bin/setup_filesystem.sh", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "DoesNotReportExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "setup_filesystem_sh_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Startup" - }, - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - } - ], - "executionDependency": [] - } - ] - }, - { - "identifier": "dlt-daemon", - "path": "/opt/apps/dlt-daemon/dltd", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "DoesNotReportExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "dlt-daemon_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Terminated", - "targetProcess_identifier": "setup_filesystem_sh" - } - ] - } - ] - }, - { - "identifier": "someip-daemon", - "path": "/opt/apps/someip/someipd", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "someip-daemon_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_someip-daemon" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [] - } - ] - }, - { - "identifier": "test_app1", - "path": "/opt/apps/test_app1/test_app1", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "test_app1_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_test_app1" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Running", - "targetProcess_identifier": "dlt-daemon" - }, - { - "stateName": "Running", - "targetProcess_identifier": "someip-daemon" - } - ] - } - ] - }, - { - "identifier": "state_manager", - "path": "/opt/apps/state_manager/sm", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "functionClusterAffiliation": "STATE_MANAGEMENT", - "startupConfig": [ - { - "executionError": "1", - "identifier": "state_manager_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Startup" - }, - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_state_manager" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Terminated", - "targetProcess_identifier": "setup_filesystem_sh" - } - ] - } - ] - } - ], - "ModeGroup": [ - { - "identifier": "MainPG", - "initialMode_name": "not-used", - "recoveryMode_name": "MainPG/fallback_run_target", - "modeDeclaration": [ - { - "identifier": "MainPG/Startup" - }, - { - "identifier": "MainPG/Full" - }, - { - "identifier": "MainPG/fallback_run_target" - } - ] - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_health_config_test/expected_output/hm_demo.json b/scripts/config_mapping/tests/empty_health_config_test/expected_output/hm_demo.json deleted file mode 100644 index eccda019d..000000000 --- a/scripts/config_mapping/tests/empty_health_config_test/expected_output/hm_demo.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "versionMajor": 8, - "versionMinor": 1, - "process": [], - "hmMonitorInterface": [], - "hmSupervisionCheckpoint": [], - "hmAliveSupervision": [] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_health_config_test/expected_output/hmcore.json b/scripts/config_mapping/tests/empty_health_config_test/expected_output/hmcore.json deleted file mode 100644 index b2c873129..000000000 --- a/scripts/config_mapping/tests/empty_health_config_test/expected_output/hmcore.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "versionMajor": 3, - "versionMinor": 0, - "watchdogs": [], - "config": [ - { - "periodicity": 123 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json new file mode 100644 index 000000000..43db9a204 --- /dev/null +++ b/scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json @@ -0,0 +1,74 @@ +{ + "schema_version": 1, + "components": [ + { + "name": "non_supervised_comp", + "description": "Non-supervised component", + "component_properties": { + "binary_name": "bin/comp", + "application_profile": { + "application_type": "Native", + "is_self_terminating": true + }, + "depends_on": [], + "process_arguments": [], + "ready_condition": { + "process_state": "Terminated" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 3, + "gid": 1000, + "supplementary_group_ids": [], + "security_policy": "", + "scheduling_policy": "OTHER", + "scheduling_priority": 0 + }, + "ready_recovery_action": { + "number_of_attempts": 0, + "delay_before_restart": 0 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + } + ], + "run_targets": [ + { + "name": "Startup", + "transition_timeout": 3, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Minimal functionality of the system", + "depends_on": [ + "non_supervised_comp" + ] + }, + { + "name": "Full", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Everything running", + "depends_on": [ + "non_supervised_comp" + ] + } + ], + "initial_run_target": "Startup", + "fallback_run_target": { + "transition_timeout": 1.5, + "description": "Switching off everything" + }, + "alive_supervision": { + "evaluation_cycle": 0.123 + } +} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hm_demo.json b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hm_demo.json deleted file mode 100644 index 90a0a9e50..000000000 --- a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hm_demo.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "versionMajor": 8, - "versionMinor": 0, - "process": [], - "hmMonitorInterface": [], - "hmSupervisionCheckpoint": [], - "hmAliveSupervision": [] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hmcore.json b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hmcore.json deleted file mode 100644 index f06adf403..000000000 --- a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/hmcore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "versionMajor": 3, - "versionMinor": 0, - "watchdogs": [ - { - "shortName": "watchdog", - "deviceFilePath": "/dev/watchdog", - "maxTimeout": 2000, - "deactivateOnShutdown": true, - "hasValueDeactivateOnShutdown": true, - "requireMagicClose": false, - "hasValueRequireMagicClose": true - } - ], - "config": [ - { - "periodicity": 500 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json new file mode 100644 index 000000000..39b7841d9 --- /dev/null +++ b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json @@ -0,0 +1,28 @@ +{ + "schema_version": 1, + "components": [], + "run_targets": [ + { + "name": "Startup", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Empty" + } + ], + "initial_run_target": "Startup", + "fallback_run_target": { + "transition_timeout": 1.5, + "description": "Switching off everything" + }, + "alive_supervision": { + "evaluation_cycle": 0.5 + }, + "watchdog": { + "device_file_path": "/dev/watchdog", + "max_timeout": 2, + "deactivate_on_shutdown": true, + "require_magic_close": false + } +} \ No newline at end of file diff --git a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_demo.json b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_demo.json deleted file mode 100644 index e51df1ee3..000000000 --- a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_demo.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "versionMajor": 7, - "versionMinor": 0, - "Process": [], - "ModeGroup": [ - { - "identifier": "MainPG", - "initialMode_name": "not-used", - "recoveryMode_name": "MainPG/fallback_run_target", - "modeDeclaration": [ - { - "identifier": "MainPG/Startup" - }, - { - "identifier": "MainPG/fallback_run_target" - } - ] - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/health_config_test/expected_output/hm_demo.json b/scripts/config_mapping/tests/health_config_test/expected_output/hm_demo.json deleted file mode 100644 index 8f560138f..000000000 --- a/scripts/config_mapping/tests/health_config_test/expected_output/hm_demo.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "versionMajor": 8, - "versionMinor": 1, - "process": [ - { - "index": 0, - "shortName": "state_manager", - "identifier": "state_manager", - "processType": "STM_PROCESS" - }, - { - "index": 1, - "shortName": "reporting_supervised_component", - "identifier": "reporting_supervised_component", - "processType": "REGULAR_PROCESS" - }, - { - "index": 2, - "shortName": "reporting_supervised_component_with_no_max_indications", - "identifier": "reporting_supervised_component_with_no_max_indications", - "processType": "REGULAR_PROCESS" - } - ], - "hmMonitorInterface": [ - { - "instanceSpecifier": "state_manager", - "processShortName": "state_manager", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_state_manager", - "refProcessIndex": 0, - "permittedUid": 4 - }, - { - "instanceSpecifier": "reporting_supervised_component", - "processShortName": "reporting_supervised_component", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_reporting_supervised_component", - "refProcessIndex": 1, - "permittedUid": 5 - }, - { - "instanceSpecifier": "reporting_supervised_component_with_no_max_indications", - "processShortName": "reporting_supervised_component_with_no_max_indications", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_reporting_supervised_component_with_no_max_indications", - "refProcessIndex": 2, - "permittedUid": 5 - } - ], - "hmSupervisionCheckpoint": [ - { - "shortName": "state_manager_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 0 - }, - { - "shortName": "reporting_supervised_component_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 1 - }, - { - "shortName": "reporting_supervised_component_with_no_max_indications_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 2 - } - ], - "hmAliveSupervision": [ - { - "ruleContextKey": "state_manager_alive_supervision", - "refCheckPointIndex": 0, - "aliveReferenceCycle": 100, - "minAliveIndications": 0, - "maxAliveIndications": 2, - "isMinCheckDisabled": true, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 0, - "refProcessIndex": 0 - }, - { - "ruleContextKey": "reporting_supervised_component_alive_supervision", - "refCheckPointIndex": 1, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 1 - }, - { - "ruleContextKey": "reporting_supervised_component_with_no_max_indications_alive_supervision", - "refCheckPointIndex": 2, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 0, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": true, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 2 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/health_config_test/expected_output/hmcore.json b/scripts/config_mapping/tests/health_config_test/expected_output/hmcore.json deleted file mode 100644 index cad238fbd..000000000 --- a/scripts/config_mapping/tests/health_config_test/expected_output/hmcore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "versionMajor": 3, - "versionMinor": 0, - "watchdogs": [ - { - "shortName": "watchdog", - "deviceFilePath": "/dev/watchdog", - "maxTimeout": 2000, - "deactivateOnShutdown": true, - "hasValueDeactivateOnShutdown": true, - "requireMagicClose": false, - "hasValueRequireMagicClose": true - } - ], - "config": [ - { - "periodicity": 123 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json new file mode 100644 index 000000000..ff57e886b --- /dev/null +++ b/scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json @@ -0,0 +1,217 @@ +{ + "schema_version": 1, + "components": [ + { + "name": "non_supervised_comp", + "description": "Non-supervised component", + "component_properties": { + "binary_name": "bin/comp", + "application_profile": { + "application_type": "Native", + "is_self_terminating": true + }, + "depends_on": [], + "process_arguments": [], + "ready_condition": { + "process_state": "Terminated" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 3, + "gid": 1000, + "supplementary_group_ids": [], + "security_policy": "", + "scheduling_policy": "OTHER", + "scheduling_priority": 0 + }, + "ready_recovery_action": { + "number_of_attempts": 0, + "delay_before_restart": 0 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "state_manager", + "description": "StateManager with min_indications set to 0", + "component_properties": { + "binary_name": "sm", + "application_profile": { + "application_type": "State_Manager", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.1, + "failed_cycles_tolerance": 0, + "min_indications": 0, + "max_indications": 2 + } + }, + "depends_on": [], + "process_arguments": [], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/state_manager", + "working_dir": "/tmp", + "sandbox": { + "uid": 4, + "gid": 1000, + "supplementary_group_ids": [], + "security_policy": "", + "scheduling_policy": "OTHER", + "scheduling_priority": 0 + }, + "ready_recovery_action": { + "number_of_attempts": 0, + "delay_before_restart": 0 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "reporting_supervised_component", + "description": "Component reporting Running state and supervised", + "component_properties": { + "binary_name": "bin/comp", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": true, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 5, + "gid": 1000, + "supplementary_group_ids": [], + "security_policy": "", + "scheduling_policy": "OTHER", + "scheduling_priority": 0 + }, + "ready_recovery_action": { + "number_of_attempts": 0, + "delay_before_restart": 0 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "reporting_supervised_component_with_no_max_indications", + "description": "Component reporting Running state and supervised with max_indications=0", + "component_properties": { + "binary_name": "bin/comp", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": true, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 0 + } + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 5, + "gid": 1000, + "supplementary_group_ids": [], + "security_policy": "", + "scheduling_policy": "OTHER", + "scheduling_priority": 0 + }, + "ready_recovery_action": { + "number_of_attempts": 0, + "delay_before_restart": 0 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + } + ], + "run_targets": [ + { + "name": "Startup", + "transition_timeout": 3, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Minimal functionality of the system", + "depends_on": [ + "state_manager" + ] + }, + { + "name": "Full", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Everything running", + "depends_on": [ + "reporting_supervised_component", + "reporting_supervised_component_with_no_max_indications", + "Startup" + ] + } + ], + "initial_run_target": "Startup", + "fallback_run_target": { + "transition_timeout": 1.5, + "description": "Switching off everything" + }, + "alive_supervision": { + "evaluation_cycle": 0.123 + }, + "watchdog": { + "device_file_path": "/dev/watchdog", + "max_timeout": 2, + "deactivate_on_shutdown": true, + "require_magic_close": false + } +} \ No newline at end of file diff --git a/scripts/config_mapping/tests/lm_config_test/expected_output/hm_demo.json b/scripts/config_mapping/tests/lm_config_test/expected_output/hm_demo.json deleted file mode 100644 index 6b627abe9..000000000 --- a/scripts/config_mapping/tests/lm_config_test/expected_output/hm_demo.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "versionMajor": 8, - "versionMinor": 0, - "process": [ - { - "index": 0, - "shortName": "test_app2", - "identifier": "test_app2", - "processType": "REGULAR_PROCESS" - }, - { - "index": 1, - "shortName": "someip-daemon", - "identifier": "someip-daemon", - "processType": "REGULAR_PROCESS" - }, - { - "index": 2, - "shortName": "test_app1", - "identifier": "test_app1", - "processType": "REGULAR_PROCESS" - }, - { - "index": 3, - "shortName": "state_manager", - "identifier": "state_manager", - "processType": "STM_PROCESS" - } - ], - "hmMonitorInterface": [ - { - "instanceSpecifier": "test_app2", - "processShortName": "test_app2", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_test_app2", - "refProcessIndex": 0, - "permittedUid": 2000 - }, - { - "instanceSpecifier": "someip-daemon", - "processShortName": "someip-daemon", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_someip-daemon", - "refProcessIndex": 1, - "permittedUid": 1000 - }, - { - "instanceSpecifier": "test_app1", - "processShortName": "test_app1", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_test_app1", - "refProcessIndex": 2, - "permittedUid": 1000 - }, - { - "instanceSpecifier": "state_manager", - "processShortName": "state_manager", - "portPrototype": "DefaultPort", - "interfacePath": "lifecycle_health_state_manager", - "refProcessIndex": 3, - "permittedUid": 1000 - } - ], - "hmSupervisionCheckpoint": [ - { - "shortName": "test_app2_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 0 - }, - { - "shortName": "someip-daemon_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 1 - }, - { - "shortName": "test_app1_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 2 - }, - { - "shortName": "state_manager_checkpoint", - "checkpointId": 1, - "refInterfaceIndex": 3 - } - ], - "hmAliveSupervision": [ - { - "ruleContextKey": "test_app2_alive_supervision", - "refCheckPointIndex": 0, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 0 - }, - { - "ruleContextKey": "someip-daemon_alive_supervision", - "refCheckPointIndex": 1, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 1 - }, - { - "ruleContextKey": "test_app1_alive_supervision", - "refCheckPointIndex": 2, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 2 - }, - { - "ruleContextKey": "state_manager_alive_supervision", - "refCheckPointIndex": 3, - "aliveReferenceCycle": 500, - "minAliveIndications": 1, - "maxAliveIndications": 3, - "isMinCheckDisabled": false, - "isMaxCheckDisabled": false, - "failedSupervisionCyclesTolerance": 2, - "refProcessIndex": 3 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/lm_config_test/expected_output/hmcore.json b/scripts/config_mapping/tests/lm_config_test/expected_output/hmcore.json deleted file mode 100644 index f06adf403..000000000 --- a/scripts/config_mapping/tests/lm_config_test/expected_output/hmcore.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "versionMajor": 3, - "versionMinor": 0, - "watchdogs": [ - { - "shortName": "watchdog", - "deviceFilePath": "/dev/watchdog", - "maxTimeout": 2000, - "deactivateOnShutdown": true, - "hasValueDeactivateOnShutdown": true, - "requireMagicClose": false, - "hasValueRequireMagicClose": true - } - ], - "config": [ - { - "periodicity": 500 - } - ] -} \ No newline at end of file diff --git a/scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json new file mode 100644 index 000000000..623cc95c3 --- /dev/null +++ b/scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json @@ -0,0 +1,445 @@ +{ + "schema_version": 1, + "components": [ + { + "name": "test_app2", + "description": "Another simple test application", + "component_properties": { + "binary_name": "test_app2", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/test_app2", + "working_dir": "/tmp", + "sandbox": { + "uid": 2000, + "gid": 2000, + "supplementary_group_ids": [ + 800, + 900 + ], + "security_policy": "policy_name_2", + "scheduling_policy": "FIFO", + "scheduling_priority": 99, + "max_memory_usage": 2048, + "max_cpu_usage": 50 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "overridden_value" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + }, + { + "key": "APP_SPECIFIC_ENV_VAR", + "value": "def" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "setup_filesystem_sh", + "description": "Script to mount partitions at the right directories", + "component_properties": { + "binary_name": "bin/setup_filesystem.sh", + "application_profile": { + "application_type": "Native", + "is_self_terminating": true + }, + "depends_on": [ + "test_app2" + ], + "process_arguments": [ + "-a", + "-b" + ], + "ready_condition": { + "process_state": "Terminated" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/scripts", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "dlt-daemon", + "description": "Logging application", + "component_properties": { + "binary_name": "dltd", + "application_profile": { + "application_type": "Native", + "is_self_terminating": false + }, + "depends_on": [ + "setup_filesystem_sh" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/dlt-daemon", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "someip-daemon", + "description": "SOME/IP application", + "component_properties": { + "binary_name": "someipd", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/someip", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "test_app1", + "description": "Simple test application", + "component_properties": { + "binary_name": "test_app1", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [ + "dlt-daemon", + "someip-daemon" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/test_app1", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + }, + { + "name": "state_manager", + "description": "Application that manages life cycle of the ECU", + "component_properties": { + "binary_name": "sm", + "application_profile": { + "application_type": "State_Manager", + "is_self_terminating": false, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3 + } + }, + "depends_on": [ + "setup_filesystem_sh" + ], + "process_arguments": [ + "-a", + "-b", + "--xyz" + ], + "ready_condition": { + "process_state": "Running" + } + }, + "deployment_config": { + "ready_timeout": 0.5, + "shutdown_timeout": 0.5, + "bin_dir": "/opt/apps/state_manager", + "working_dir": "/tmp", + "sandbox": { + "uid": 1000, + "gid": 1000, + "supplementary_group_ids": [ + 500, + 600, + 700 + ], + "security_policy": "policy_name", + "scheduling_policy": "OTHER", + "scheduling_priority": 0, + "max_memory_usage": 1024, + "max_cpu_usage": 75 + }, + "environmental_variables": [ + { + "key": "LD_LIBRARY_PATH", + "value": "/opt/lib" + }, + { + "key": "GLOBAL_ENV_VAR", + "value": "abc" + }, + { + "key": "EMPTY_GLOBAL_ENV_VAR", + "value": "" + } + ], + "ready_recovery_action": { + "number_of_attempts": 1, + "delay_before_restart": 0.5 + }, + "recovery_action": { + "run_target": "fallback_run_target" + } + } + } + ], + "run_targets": [ + { + "name": "Startup", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Minimal functionality of the system", + "depends_on": [ + "state_manager" + ] + }, + { + "name": "Full", + "transition_timeout": 5, + "recovery_action": { + "run_target": "fallback_run_target" + }, + "description": "Everything running", + "depends_on": [ + "test_app1", + "Startup" + ] + } + ], + "initial_run_target": "Startup", + "fallback_run_target": { + "transition_timeout": 1.5, + "description": "Switching off everything" + }, + "alive_supervision": { + "evaluation_cycle": 0.5 + }, + "watchdog": { + "device_file_path": "/dev/watchdog", + "max_timeout": 2, + "deactivate_on_shutdown": true, + "require_magic_close": false + } +} \ No newline at end of file diff --git a/scripts/config_mapping/tests/lm_config_test/expected_output/lm_demo.json b/scripts/config_mapping/tests/lm_config_test/expected_output/lm_demo.json deleted file mode 100644 index 9f3359192..000000000 --- a/scripts/config_mapping/tests/lm_config_test/expected_output/lm_demo.json +++ /dev/null @@ -1,453 +0,0 @@ -{ - "versionMajor": 7, - "versionMinor": 0, - "Process": [ - { - "identifier": "test_app2", - "path": "/opt/apps/test_app2/test_app2", - "uid": 2000, - "gid": 2000, - "sgids": [ - { - "sgid": 800 - }, - { - "sgid": 900 - } - ], - "securityPolicyDetails": "policy_name_2", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "test_app2_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_FIFO", - "schedulingPriority": "99", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Startup" - }, - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "overridden_value" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "APP_SPECIFIC_ENV_VAR", - "value": "def" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_test_app2" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [] - } - ] - }, - { - "identifier": "setup_filesystem_sh", - "path": "/opt/scripts/bin/setup_filesystem.sh", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "DoesNotReportExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "setup_filesystem_sh_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Startup" - }, - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - } - ], - "executionDependency": [ - { - "stateName": "Running", - "targetProcess_identifier": "test_app2" - } - ] - } - ] - }, - { - "identifier": "dlt-daemon", - "path": "/opt/apps/dlt-daemon/dltd", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "DoesNotReportExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "dlt-daemon_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Terminated", - "targetProcess_identifier": "setup_filesystem_sh" - } - ] - } - ] - }, - { - "identifier": "someip-daemon", - "path": "/opt/apps/someip/someipd", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "someip-daemon_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_someip-daemon" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [] - } - ] - }, - { - "identifier": "test_app1", - "path": "/opt/apps/test_app1/test_app1", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "startupConfig": [ - { - "executionError": "1", - "identifier": "test_app1_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_test_app1" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Running", - "targetProcess_identifier": "dlt-daemon" - }, - { - "stateName": "Running", - "targetProcess_identifier": "someip-daemon" - } - ] - } - ] - }, - { - "identifier": "state_manager", - "path": "/opt/apps/state_manager/sm", - "uid": 1000, - "gid": 1000, - "sgids": [ - { - "sgid": 500 - }, - { - "sgid": 600 - }, - { - "sgid": 700 - } - ], - "securityPolicyDetails": "policy_name", - "numberOfRestartAttempts": 1, - "executable_reportingBehavior": "ReportsExecutionState", - "functionClusterAffiliation": "STATE_MANAGEMENT", - "startupConfig": [ - { - "executionError": "1", - "identifier": "state_manager_startup_config", - "enterTimeoutValue": 500, - "exitTimeoutValue": 500, - "schedulingPolicy": "SCHED_OTHER", - "schedulingPriority": "0", - "terminationBehavior": "ProcessIsNotSelfTerminating", - "processGroupStateDependency": [ - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Startup" - }, - { - "stateMachine_name": "MainPG", - "stateName": "MainPG/Full" - } - ], - "environmentVariable": [ - { - "key": "LD_LIBRARY_PATH", - "value": "/opt/lib" - }, - { - "key": "GLOBAL_ENV_VAR", - "value": "abc" - }, - { - "key": "EMPTY_GLOBAL_ENV_VAR", - "value": "" - }, - { - "key": "LCM_ALIVE_INTERFACE_PATH", - "value": "lifecycle_health_state_manager" - } - ], - "processArgument": [ - { - "argument": "-a" - }, - { - "argument": "-b" - }, - { - "argument": "--xyz" - } - ], - "executionDependency": [ - { - "stateName": "Terminated", - "targetProcess_identifier": "setup_filesystem_sh" - } - ] - } - ] - } - ], - "ModeGroup": [ - { - "identifier": "MainPG", - "initialMode_name": "not-used", - "recoveryMode_name": "MainPG/fallback_run_target", - "modeDeclaration": [ - { - "identifier": "MainPG/Startup" - }, - { - "identifier": "MainPG/Full" - }, - { - "identifier": "MainPG/fallback_run_target" - } - ] - } - ] -} \ No newline at end of file From eb807a15d05886f59c0a9507d20858d004814972 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Wed, 17 Jun 2026 20:57:54 +0200 Subject: [PATCH 2/7] Before self review --- score/launch_manager/daemon/BUILD | 1 + .../daemon/src/alive_monitor/BUILD | 25 - .../src/alive_monitor/config/hm_flatcfg.fbs | 68 - .../config/hm_flatcfg_generated.h | 806 ------------ .../alive_monitor/config/hmcore_flatcfg.fbs | 31 - .../config/hmcore_flatcfg_generated.h | 371 ------ .../daemon/src/alive_monitor/details/BUILD | 1 - .../details/daemon/AliveMonitorImpl.cpp | 21 +- .../details/daemon/AliveMonitorImpl.hpp | 7 +- .../src/alive_monitor/details/daemon/BUILD | 2 +- .../daemon/src/configuration/BUILD | 20 - .../configuration/configuration_adapter.cpp | 14 +- .../configuration/configuration_adapter.hpp | 11 +- .../daemon/src/configuration/lm_flatcfg.fbs | 90 -- .../src/configuration/lm_flatcfg_generated.h | 1105 ----------------- score/launch_manager/daemon/src/main.cpp | 47 +- .../daemon/src/process_group_manager/BUILD | 1 + .../details/process_group_manager.cpp | 8 +- .../process_group_manager.hpp | 9 +- .../complex_monitoring/complex_monitoring.py | 1 + .../crash_on_startup/crash_on_startup.py | 1 + .../incorrect_config_non_reporting/BUILD | 4 - .../test_incorrect_config_non_reporting.py | 1 + .../process_crash_monitoring.py | 1 + .../process_launch_args.py | 1 + tests/integration/smoke/BUILD | 9 - tests/integration/smoke/smoke.py | 1 + .../switch_run_target/switch_run_target.py | 1 + 28 files changed, 71 insertions(+), 2587 deletions(-) delete mode 100644 score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg.fbs delete mode 100644 score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg_generated.h delete mode 100644 score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg.fbs delete mode 100644 score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg_generated.h delete mode 100644 score/launch_manager/daemon/src/configuration/lm_flatcfg.fbs delete mode 100644 score/launch_manager/daemon/src/configuration/lm_flatcfg_generated.h diff --git a/score/launch_manager/daemon/BUILD b/score/launch_manager/daemon/BUILD index e7dd68935..8996a61db 100644 --- a/score/launch_manager/daemon/BUILD +++ b/score/launch_manager/daemon/BUILD @@ -35,6 +35,7 @@ cc_binary( deps = [ "//score/launch_manager/daemon/src/alive_monitor", "//score/launch_manager/daemon/src/common:log", + "//score/launch_manager/daemon/src/configuration:flatbuffer_config_loader", "//score/launch_manager/daemon/src/osal:ipc_comms", "//score/launch_manager/daemon/src/process_group_manager", "//score/launch_manager/daemon/src/process_group_manager:alive_monitor_thread", diff --git a/score/launch_manager/daemon/src/alive_monitor/BUILD b/score/launch_manager/daemon/src/alive_monitor/BUILD index 1f208d17b..d46cb7a7b 100644 --- a/score/launch_manager/daemon/src/alive_monitor/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/BUILD @@ -12,31 +12,6 @@ # ******************************************************************************* load("@rules_cc//cc:defs.bzl", "cc_library") -filegroup( - name = "am_flatcfg_fbs", - srcs = ["config/hm_flatcfg.fbs"], - visibility = ["//visibility:public"], -) - -filegroup( - name = "am_core_flatcfg_fbs", - srcs = ["config/hmcore_flatcfg.fbs"], - visibility = ["//visibility:public"], -) - -exports_files(["config/hm_flatcfg.fbs"]) - -cc_library( - name = "config", - hdrs = [ - "config/hm_flatcfg_generated.h", - "config/hmcore_flatcfg_generated.h", - ], - include_prefix = "score/mw/launch_manager/alive_monitor", - strip_include_prefix = "/score/launch_manager/daemon/src/alive_monitor", - visibility = ["//score/launch_manager/daemon/src/alive_monitor:__subpackages__"], -) - cc_library( name = "alive_monitor_h", hdrs = [ diff --git a/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg.fbs b/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg.fbs deleted file mode 100644 index 05f1741f1..000000000 --- a/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg.fbs +++ /dev/null @@ -1,68 +0,0 @@ -namespace HMFlatBuffer; - -// HM version 8.1 - -file_identifier "BHMT"; -file_extension "bin"; - -enum ProcessType : byte { - REGULAR_PROCESS = 0, // REGULAR_PROCESS - LM_PROCESS = 1, // LM_PROCESS - STM_PROCESS = 2 // STM_PROCESS -} - -table HMEcuCfg { - versionMajor: int (id:0); - versionMinor: int (id:1); - process: [Process] (id:2); - hmMonitorInterface: [HmMonitorInterface] (id:3); - hmSupervisionCheckpoint: [HmSupervisionCheckpoint] (id:4); - hmAliveSupervision: [HmAliveSupervision] (id:5); -} - -table Process { - shortName: string (id:0); - identifier: string (id:1); - index: uint32 (id:2); - processType: ProcessType (id:3); -} - -table HmRefProcess { - index: uint32 (id:0); -} - -table HmMonitorInterface { - instanceSpecifier: string (id:0); - processShortName: string (id:1); - portPrototype: string (id:2); - interfacePath: string (id:3); - refProcessIndex: uint32 (id:4); - permittedUid: int32 (id:5); -} - -table HmSupervisionCheckpoint { - shortName: string (id:0); - checkpointId: uint32 (id:1); - refInterfaceIndex: uint32 (id:2); -} - -table HmCheckpointTransition { - refSourceCPIndex: uint32 (id:0); - refTargetCPIndex: uint32 (id:1); - infoSource: HmSupervisionCheckpoint (id:2); - infoTarget: HmSupervisionCheckpoint (id:3); -} - -table HmAliveSupervision { - ruleContextKey: string (id:0); - refCheckPointIndex: uint32 (id:1); - aliveReferenceCycle: double (id:2); - minAliveIndications: uint32 (id:3); - maxAliveIndications: uint32 (id:4); - isMinCheckDisabled: bool (id:5); - isMaxCheckDisabled: bool (id:6); - failedSupervisionCyclesTolerance: uint32 (id:7); - refProcessIndex: uint32 (id:8); -} - -root_type HMEcuCfg; diff --git a/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg_generated.h b/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg_generated.h deleted file mode 100644 index 29497d506..000000000 --- a/score/launch_manager/daemon/src/alive_monitor/config/hm_flatcfg_generated.h +++ /dev/null @@ -1,806 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_HMFLATCFG_HMFLATBUFFER_H_ -#define FLATBUFFERS_GENERATED_HMFLATCFG_HMFLATBUFFER_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && - FLATBUFFERS_VERSION_MINOR == 12 && - FLATBUFFERS_VERSION_REVISION == 19, - "Non-compatible flatbuffers version included"); - -namespace HMFlatBuffer { - -struct HMEcuCfg; -struct HMEcuCfgBuilder; - -struct Process; -struct ProcessBuilder; - -struct HmRefProcess; -struct HmRefProcessBuilder; - -struct HmMonitorInterface; -struct HmMonitorInterfaceBuilder; - -struct HmSupervisionCheckpoint; -struct HmSupervisionCheckpointBuilder; - -struct HmCheckpointTransition; -struct HmCheckpointTransitionBuilder; - -struct HmAliveSupervision; -struct HmAliveSupervisionBuilder; - -enum ProcessType : int8_t { - ProcessType_REGULAR_PROCESS = 0, - ProcessType_LM_PROCESS = 1, - ProcessType_STM_PROCESS = 2, - ProcessType_MIN = ProcessType_REGULAR_PROCESS, - ProcessType_MAX = ProcessType_STM_PROCESS -}; - -inline const ProcessType (&EnumValuesProcessType())[3] { - static const ProcessType values[] = { - ProcessType_REGULAR_PROCESS, - ProcessType_LM_PROCESS, - ProcessType_STM_PROCESS - }; - return values; -} - -inline const char * const *EnumNamesProcessType() { - static const char * const names[4] = { - "REGULAR_PROCESS", - "LM_PROCESS", - "STM_PROCESS", - nullptr - }; - return names; -} - -inline const char *EnumNameProcessType(ProcessType e) { - if (::flatbuffers::IsOutRange(e, ProcessType_REGULAR_PROCESS, ProcessType_STM_PROCESS)) return ""; - const size_t index = static_cast(e); - return EnumNamesProcessType()[index]; -} - -struct HMEcuCfg FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HMEcuCfgBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_VERSIONMAJOR = 4, - VT_VERSIONMINOR = 6, - VT_PROCESS = 8, - VT_HMMONITORINTERFACE = 10, - VT_HMSUPERVISIONCHECKPOINT = 12, - VT_HMALIVESUPERVISION = 14 - }; - int32_t versionMajor() const { - return GetField(VT_VERSIONMAJOR, 0); - } - int32_t versionMinor() const { - return GetField(VT_VERSIONMINOR, 0); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *process() const { - return GetPointer> *>(VT_PROCESS); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *hmMonitorInterface() const { - return GetPointer> *>(VT_HMMONITORINTERFACE); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *hmSupervisionCheckpoint() const { - return GetPointer> *>(VT_HMSUPERVISIONCHECKPOINT); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *hmAliveSupervision() const { - return GetPointer> *>(VT_HMALIVESUPERVISION); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_VERSIONMAJOR, 4) && - VerifyField(verifier, VT_VERSIONMINOR, 4) && - VerifyOffset(verifier, VT_PROCESS) && - verifier.VerifyVector(process()) && - verifier.VerifyVectorOfTables(process()) && - VerifyOffset(verifier, VT_HMMONITORINTERFACE) && - verifier.VerifyVector(hmMonitorInterface()) && - verifier.VerifyVectorOfTables(hmMonitorInterface()) && - VerifyOffset(verifier, VT_HMSUPERVISIONCHECKPOINT) && - verifier.VerifyVector(hmSupervisionCheckpoint()) && - verifier.VerifyVectorOfTables(hmSupervisionCheckpoint()) && - VerifyOffset(verifier, VT_HMALIVESUPERVISION) && - verifier.VerifyVector(hmAliveSupervision()) && - verifier.VerifyVectorOfTables(hmAliveSupervision()) && - verifier.EndTable(); - } -}; - -struct HMEcuCfgBuilder { - typedef HMEcuCfg Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_versionMajor(int32_t versionMajor) { - fbb_.AddElement(HMEcuCfg::VT_VERSIONMAJOR, versionMajor, 0); - } - void add_versionMinor(int32_t versionMinor) { - fbb_.AddElement(HMEcuCfg::VT_VERSIONMINOR, versionMinor, 0); - } - void add_process(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> process) { - fbb_.AddOffset(HMEcuCfg::VT_PROCESS, process); - } - void add_hmMonitorInterface(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmMonitorInterface) { - fbb_.AddOffset(HMEcuCfg::VT_HMMONITORINTERFACE, hmMonitorInterface); - } - void add_hmSupervisionCheckpoint(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmSupervisionCheckpoint) { - fbb_.AddOffset(HMEcuCfg::VT_HMSUPERVISIONCHECKPOINT, hmSupervisionCheckpoint); - } - void add_hmAliveSupervision(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmAliveSupervision) { - fbb_.AddOffset(HMEcuCfg::VT_HMALIVESUPERVISION, hmAliveSupervision); - } - explicit HMEcuCfgBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHMEcuCfg( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> process = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmMonitorInterface = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmSupervisionCheckpoint = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> hmAliveSupervision = 0) { - HMEcuCfgBuilder builder_(_fbb); - builder_.add_hmAliveSupervision(hmAliveSupervision); - builder_.add_hmSupervisionCheckpoint(hmSupervisionCheckpoint); - builder_.add_hmMonitorInterface(hmMonitorInterface); - builder_.add_process(process); - builder_.add_versionMinor(versionMinor); - builder_.add_versionMajor(versionMajor); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateHMEcuCfgDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - const std::vector<::flatbuffers::Offset> *process = nullptr, - const std::vector<::flatbuffers::Offset> *hmMonitorInterface = nullptr, - const std::vector<::flatbuffers::Offset> *hmSupervisionCheckpoint = nullptr, - const std::vector<::flatbuffers::Offset> *hmAliveSupervision = nullptr) { - auto process__ = process ? _fbb.CreateVector<::flatbuffers::Offset>(*process) : 0; - auto hmMonitorInterface__ = hmMonitorInterface ? _fbb.CreateVector<::flatbuffers::Offset>(*hmMonitorInterface) : 0; - auto hmSupervisionCheckpoint__ = hmSupervisionCheckpoint ? _fbb.CreateVector<::flatbuffers::Offset>(*hmSupervisionCheckpoint) : 0; - auto hmAliveSupervision__ = hmAliveSupervision ? _fbb.CreateVector<::flatbuffers::Offset>(*hmAliveSupervision) : 0; - return HMFlatBuffer::CreateHMEcuCfg( - _fbb, - versionMajor, - versionMinor, - process__, - hmMonitorInterface__, - hmSupervisionCheckpoint__, - hmAliveSupervision__); -} - -struct Process FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SHORTNAME = 4, - VT_IDENTIFIER = 6, - VT_INDEX = 8, - VT_PROCESSTYPE = 10 - }; - const ::flatbuffers::String *shortName() const { - return GetPointer(VT_SHORTNAME); - } - const ::flatbuffers::String *identifier() const { - return GetPointer(VT_IDENTIFIER); - } - uint32_t index() const { - return GetField(VT_INDEX, 0); - } - HMFlatBuffer::ProcessType processType() const { - return static_cast(GetField(VT_PROCESSTYPE, 0)); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SHORTNAME) && - verifier.VerifyString(shortName()) && - VerifyOffset(verifier, VT_IDENTIFIER) && - verifier.VerifyString(identifier()) && - VerifyField(verifier, VT_INDEX, 4) && - VerifyField(verifier, VT_PROCESSTYPE, 1) && - verifier.EndTable(); - } -}; - -struct ProcessBuilder { - typedef Process Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_shortName(::flatbuffers::Offset<::flatbuffers::String> shortName) { - fbb_.AddOffset(Process::VT_SHORTNAME, shortName); - } - void add_identifier(::flatbuffers::Offset<::flatbuffers::String> identifier) { - fbb_.AddOffset(Process::VT_IDENTIFIER, identifier); - } - void add_index(uint32_t index) { - fbb_.AddElement(Process::VT_INDEX, index, 0); - } - void add_processType(HMFlatBuffer::ProcessType processType) { - fbb_.AddElement(Process::VT_PROCESSTYPE, static_cast(processType), 0); - } - explicit ProcessBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcess( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> shortName = 0, - ::flatbuffers::Offset<::flatbuffers::String> identifier = 0, - uint32_t index = 0, - HMFlatBuffer::ProcessType processType = HMFlatBuffer::ProcessType_REGULAR_PROCESS) { - ProcessBuilder builder_(_fbb); - builder_.add_index(index); - builder_.add_identifier(identifier); - builder_.add_shortName(shortName); - builder_.add_processType(processType); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *shortName = nullptr, - const char *identifier = nullptr, - uint32_t index = 0, - HMFlatBuffer::ProcessType processType = HMFlatBuffer::ProcessType_REGULAR_PROCESS) { - auto shortName__ = shortName ? _fbb.CreateString(shortName) : 0; - auto identifier__ = identifier ? _fbb.CreateString(identifier) : 0; - return HMFlatBuffer::CreateProcess( - _fbb, - shortName__, - identifier__, - index, - processType); -} - -struct HmRefProcess FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmRefProcessBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_INDEX = 4 - }; - uint32_t index() const { - return GetField(VT_INDEX, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_INDEX, 4) && - verifier.EndTable(); - } -}; - -struct HmRefProcessBuilder { - typedef HmRefProcess Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_index(uint32_t index) { - fbb_.AddElement(HmRefProcess::VT_INDEX, index, 0); - } - explicit HmRefProcessBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmRefProcess( - ::flatbuffers::FlatBufferBuilder &_fbb, - uint32_t index = 0) { - HmRefProcessBuilder builder_(_fbb); - builder_.add_index(index); - return builder_.Finish(); -} - -struct HmMonitorInterface FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmMonitorInterfaceBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_INSTANCESPECIFIER = 4, - VT_PROCESSSHORTNAME = 6, - VT_PORTPROTOTYPE = 8, - VT_INTERFACEPATH = 10, - VT_REFPROCESSINDEX = 12, - VT_PERMITTEDUID = 14 - }; - const ::flatbuffers::String *instanceSpecifier() const { - return GetPointer(VT_INSTANCESPECIFIER); - } - const ::flatbuffers::String *processShortName() const { - return GetPointer(VT_PROCESSSHORTNAME); - } - const ::flatbuffers::String *portPrototype() const { - return GetPointer(VT_PORTPROTOTYPE); - } - const ::flatbuffers::String *interfacePath() const { - return GetPointer(VT_INTERFACEPATH); - } - uint32_t refProcessIndex() const { - return GetField(VT_REFPROCESSINDEX, 0); - } - int32_t permittedUid() const { - return GetField(VT_PERMITTEDUID, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_INSTANCESPECIFIER) && - verifier.VerifyString(instanceSpecifier()) && - VerifyOffset(verifier, VT_PROCESSSHORTNAME) && - verifier.VerifyString(processShortName()) && - VerifyOffset(verifier, VT_PORTPROTOTYPE) && - verifier.VerifyString(portPrototype()) && - VerifyOffset(verifier, VT_INTERFACEPATH) && - verifier.VerifyString(interfacePath()) && - VerifyField(verifier, VT_REFPROCESSINDEX, 4) && - VerifyField(verifier, VT_PERMITTEDUID, 4) && - verifier.EndTable(); - } -}; - -struct HmMonitorInterfaceBuilder { - typedef HmMonitorInterface Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_instanceSpecifier(::flatbuffers::Offset<::flatbuffers::String> instanceSpecifier) { - fbb_.AddOffset(HmMonitorInterface::VT_INSTANCESPECIFIER, instanceSpecifier); - } - void add_processShortName(::flatbuffers::Offset<::flatbuffers::String> processShortName) { - fbb_.AddOffset(HmMonitorInterface::VT_PROCESSSHORTNAME, processShortName); - } - void add_portPrototype(::flatbuffers::Offset<::flatbuffers::String> portPrototype) { - fbb_.AddOffset(HmMonitorInterface::VT_PORTPROTOTYPE, portPrototype); - } - void add_interfacePath(::flatbuffers::Offset<::flatbuffers::String> interfacePath) { - fbb_.AddOffset(HmMonitorInterface::VT_INTERFACEPATH, interfacePath); - } - void add_refProcessIndex(uint32_t refProcessIndex) { - fbb_.AddElement(HmMonitorInterface::VT_REFPROCESSINDEX, refProcessIndex, 0); - } - void add_permittedUid(int32_t permittedUid) { - fbb_.AddElement(HmMonitorInterface::VT_PERMITTEDUID, permittedUid, 0); - } - explicit HmMonitorInterfaceBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmMonitorInterface( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> instanceSpecifier = 0, - ::flatbuffers::Offset<::flatbuffers::String> processShortName = 0, - ::flatbuffers::Offset<::flatbuffers::String> portPrototype = 0, - ::flatbuffers::Offset<::flatbuffers::String> interfacePath = 0, - uint32_t refProcessIndex = 0, - int32_t permittedUid = 0) { - HmMonitorInterfaceBuilder builder_(_fbb); - builder_.add_permittedUid(permittedUid); - builder_.add_refProcessIndex(refProcessIndex); - builder_.add_interfacePath(interfacePath); - builder_.add_portPrototype(portPrototype); - builder_.add_processShortName(processShortName); - builder_.add_instanceSpecifier(instanceSpecifier); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateHmMonitorInterfaceDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *instanceSpecifier = nullptr, - const char *processShortName = nullptr, - const char *portPrototype = nullptr, - const char *interfacePath = nullptr, - uint32_t refProcessIndex = 0, - int32_t permittedUid = 0) { - auto instanceSpecifier__ = instanceSpecifier ? _fbb.CreateString(instanceSpecifier) : 0; - auto processShortName__ = processShortName ? _fbb.CreateString(processShortName) : 0; - auto portPrototype__ = portPrototype ? _fbb.CreateString(portPrototype) : 0; - auto interfacePath__ = interfacePath ? _fbb.CreateString(interfacePath) : 0; - return HMFlatBuffer::CreateHmMonitorInterface( - _fbb, - instanceSpecifier__, - processShortName__, - portPrototype__, - interfacePath__, - refProcessIndex, - permittedUid); -} - -struct HmSupervisionCheckpoint FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmSupervisionCheckpointBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SHORTNAME = 4, - VT_CHECKPOINTID = 6, - VT_REFINTERFACEINDEX = 8 - }; - const ::flatbuffers::String *shortName() const { - return GetPointer(VT_SHORTNAME); - } - uint32_t checkpointId() const { - return GetField(VT_CHECKPOINTID, 0); - } - uint32_t refInterfaceIndex() const { - return GetField(VT_REFINTERFACEINDEX, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SHORTNAME) && - verifier.VerifyString(shortName()) && - VerifyField(verifier, VT_CHECKPOINTID, 4) && - VerifyField(verifier, VT_REFINTERFACEINDEX, 4) && - verifier.EndTable(); - } -}; - -struct HmSupervisionCheckpointBuilder { - typedef HmSupervisionCheckpoint Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_shortName(::flatbuffers::Offset<::flatbuffers::String> shortName) { - fbb_.AddOffset(HmSupervisionCheckpoint::VT_SHORTNAME, shortName); - } - void add_checkpointId(uint32_t checkpointId) { - fbb_.AddElement(HmSupervisionCheckpoint::VT_CHECKPOINTID, checkpointId, 0); - } - void add_refInterfaceIndex(uint32_t refInterfaceIndex) { - fbb_.AddElement(HmSupervisionCheckpoint::VT_REFINTERFACEINDEX, refInterfaceIndex, 0); - } - explicit HmSupervisionCheckpointBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmSupervisionCheckpoint( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> shortName = 0, - uint32_t checkpointId = 0, - uint32_t refInterfaceIndex = 0) { - HmSupervisionCheckpointBuilder builder_(_fbb); - builder_.add_refInterfaceIndex(refInterfaceIndex); - builder_.add_checkpointId(checkpointId); - builder_.add_shortName(shortName); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateHmSupervisionCheckpointDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *shortName = nullptr, - uint32_t checkpointId = 0, - uint32_t refInterfaceIndex = 0) { - auto shortName__ = shortName ? _fbb.CreateString(shortName) : 0; - return HMFlatBuffer::CreateHmSupervisionCheckpoint( - _fbb, - shortName__, - checkpointId, - refInterfaceIndex); -} - -struct HmCheckpointTransition FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmCheckpointTransitionBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_REFSOURCECPINDEX = 4, - VT_REFTARGETCPINDEX = 6, - VT_INFOSOURCE = 8, - VT_INFOTARGET = 10 - }; - uint32_t refSourceCPIndex() const { - return GetField(VT_REFSOURCECPINDEX, 0); - } - uint32_t refTargetCPIndex() const { - return GetField(VT_REFTARGETCPINDEX, 0); - } - const HMFlatBuffer::HmSupervisionCheckpoint *infoSource() const { - return GetPointer(VT_INFOSOURCE); - } - const HMFlatBuffer::HmSupervisionCheckpoint *infoTarget() const { - return GetPointer(VT_INFOTARGET); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_REFSOURCECPINDEX, 4) && - VerifyField(verifier, VT_REFTARGETCPINDEX, 4) && - VerifyOffset(verifier, VT_INFOSOURCE) && - verifier.VerifyTable(infoSource()) && - VerifyOffset(verifier, VT_INFOTARGET) && - verifier.VerifyTable(infoTarget()) && - verifier.EndTable(); - } -}; - -struct HmCheckpointTransitionBuilder { - typedef HmCheckpointTransition Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_refSourceCPIndex(uint32_t refSourceCPIndex) { - fbb_.AddElement(HmCheckpointTransition::VT_REFSOURCECPINDEX, refSourceCPIndex, 0); - } - void add_refTargetCPIndex(uint32_t refTargetCPIndex) { - fbb_.AddElement(HmCheckpointTransition::VT_REFTARGETCPINDEX, refTargetCPIndex, 0); - } - void add_infoSource(::flatbuffers::Offset infoSource) { - fbb_.AddOffset(HmCheckpointTransition::VT_INFOSOURCE, infoSource); - } - void add_infoTarget(::flatbuffers::Offset infoTarget) { - fbb_.AddOffset(HmCheckpointTransition::VT_INFOTARGET, infoTarget); - } - explicit HmCheckpointTransitionBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmCheckpointTransition( - ::flatbuffers::FlatBufferBuilder &_fbb, - uint32_t refSourceCPIndex = 0, - uint32_t refTargetCPIndex = 0, - ::flatbuffers::Offset infoSource = 0, - ::flatbuffers::Offset infoTarget = 0) { - HmCheckpointTransitionBuilder builder_(_fbb); - builder_.add_infoTarget(infoTarget); - builder_.add_infoSource(infoSource); - builder_.add_refTargetCPIndex(refTargetCPIndex); - builder_.add_refSourceCPIndex(refSourceCPIndex); - return builder_.Finish(); -} - -struct HmAliveSupervision FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmAliveSupervisionBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_RULECONTEXTKEY = 4, - VT_REFCHECKPOINTINDEX = 6, - VT_ALIVEREFERENCECYCLE = 8, - VT_MINALIVEINDICATIONS = 10, - VT_MAXALIVEINDICATIONS = 12, - VT_ISMINCHECKDISABLED = 14, - VT_ISMAXCHECKDISABLED = 16, - VT_FAILEDSUPERVISIONCYCLESTOLERANCE = 18, - VT_REFPROCESSINDEX = 20 - }; - const ::flatbuffers::String *ruleContextKey() const { - return GetPointer(VT_RULECONTEXTKEY); - } - uint32_t refCheckPointIndex() const { - return GetField(VT_REFCHECKPOINTINDEX, 0); - } - double aliveReferenceCycle() const { - return GetField(VT_ALIVEREFERENCECYCLE, 0.0); - } - uint32_t minAliveIndications() const { - return GetField(VT_MINALIVEINDICATIONS, 0); - } - uint32_t maxAliveIndications() const { - return GetField(VT_MAXALIVEINDICATIONS, 0); - } - bool isMinCheckDisabled() const { - return GetField(VT_ISMINCHECKDISABLED, 0) != 0; - } - bool isMaxCheckDisabled() const { - return GetField(VT_ISMAXCHECKDISABLED, 0) != 0; - } - uint32_t failedSupervisionCyclesTolerance() const { - return GetField(VT_FAILEDSUPERVISIONCYCLESTOLERANCE, 0); - } - uint32_t refProcessIndex() const { - return GetField(VT_REFPROCESSINDEX, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_RULECONTEXTKEY) && - verifier.VerifyString(ruleContextKey()) && - VerifyField(verifier, VT_REFCHECKPOINTINDEX, 4) && - VerifyField(verifier, VT_ALIVEREFERENCECYCLE, 8) && - VerifyField(verifier, VT_MINALIVEINDICATIONS, 4) && - VerifyField(verifier, VT_MAXALIVEINDICATIONS, 4) && - VerifyField(verifier, VT_ISMINCHECKDISABLED, 1) && - VerifyField(verifier, VT_ISMAXCHECKDISABLED, 1) && - VerifyField(verifier, VT_FAILEDSUPERVISIONCYCLESTOLERANCE, 4) && - VerifyField(verifier, VT_REFPROCESSINDEX, 4) && - verifier.EndTable(); - } -}; - -struct HmAliveSupervisionBuilder { - typedef HmAliveSupervision Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_ruleContextKey(::flatbuffers::Offset<::flatbuffers::String> ruleContextKey) { - fbb_.AddOffset(HmAliveSupervision::VT_RULECONTEXTKEY, ruleContextKey); - } - void add_refCheckPointIndex(uint32_t refCheckPointIndex) { - fbb_.AddElement(HmAliveSupervision::VT_REFCHECKPOINTINDEX, refCheckPointIndex, 0); - } - void add_aliveReferenceCycle(double aliveReferenceCycle) { - fbb_.AddElement(HmAliveSupervision::VT_ALIVEREFERENCECYCLE, aliveReferenceCycle, 0.0); - } - void add_minAliveIndications(uint32_t minAliveIndications) { - fbb_.AddElement(HmAliveSupervision::VT_MINALIVEINDICATIONS, minAliveIndications, 0); - } - void add_maxAliveIndications(uint32_t maxAliveIndications) { - fbb_.AddElement(HmAliveSupervision::VT_MAXALIVEINDICATIONS, maxAliveIndications, 0); - } - void add_isMinCheckDisabled(bool isMinCheckDisabled) { - fbb_.AddElement(HmAliveSupervision::VT_ISMINCHECKDISABLED, static_cast(isMinCheckDisabled), 0); - } - void add_isMaxCheckDisabled(bool isMaxCheckDisabled) { - fbb_.AddElement(HmAliveSupervision::VT_ISMAXCHECKDISABLED, static_cast(isMaxCheckDisabled), 0); - } - void add_failedSupervisionCyclesTolerance(uint32_t failedSupervisionCyclesTolerance) { - fbb_.AddElement(HmAliveSupervision::VT_FAILEDSUPERVISIONCYCLESTOLERANCE, failedSupervisionCyclesTolerance, 0); - } - void add_refProcessIndex(uint32_t refProcessIndex) { - fbb_.AddElement(HmAliveSupervision::VT_REFPROCESSINDEX, refProcessIndex, 0); - } - explicit HmAliveSupervisionBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmAliveSupervision( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> ruleContextKey = 0, - uint32_t refCheckPointIndex = 0, - double aliveReferenceCycle = 0.0, - uint32_t minAliveIndications = 0, - uint32_t maxAliveIndications = 0, - bool isMinCheckDisabled = false, - bool isMaxCheckDisabled = false, - uint32_t failedSupervisionCyclesTolerance = 0, - uint32_t refProcessIndex = 0) { - HmAliveSupervisionBuilder builder_(_fbb); - builder_.add_aliveReferenceCycle(aliveReferenceCycle); - builder_.add_refProcessIndex(refProcessIndex); - builder_.add_failedSupervisionCyclesTolerance(failedSupervisionCyclesTolerance); - builder_.add_maxAliveIndications(maxAliveIndications); - builder_.add_minAliveIndications(minAliveIndications); - builder_.add_refCheckPointIndex(refCheckPointIndex); - builder_.add_ruleContextKey(ruleContextKey); - builder_.add_isMaxCheckDisabled(isMaxCheckDisabled); - builder_.add_isMinCheckDisabled(isMinCheckDisabled); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateHmAliveSupervisionDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *ruleContextKey = nullptr, - uint32_t refCheckPointIndex = 0, - double aliveReferenceCycle = 0.0, - uint32_t minAliveIndications = 0, - uint32_t maxAliveIndications = 0, - bool isMinCheckDisabled = false, - bool isMaxCheckDisabled = false, - uint32_t failedSupervisionCyclesTolerance = 0, - uint32_t refProcessIndex = 0) { - auto ruleContextKey__ = ruleContextKey ? _fbb.CreateString(ruleContextKey) : 0; - return HMFlatBuffer::CreateHmAliveSupervision( - _fbb, - ruleContextKey__, - refCheckPointIndex, - aliveReferenceCycle, - minAliveIndications, - maxAliveIndications, - isMinCheckDisabled, - isMaxCheckDisabled, - failedSupervisionCyclesTolerance, - refProcessIndex); -} - -inline const HMFlatBuffer::HMEcuCfg *GetHMEcuCfg(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const HMFlatBuffer::HMEcuCfg *GetSizePrefixedHMEcuCfg(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline const char *HMEcuCfgIdentifier() { - return "BHMT"; -} - -inline bool HMEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, HMEcuCfgIdentifier()); -} - -inline bool SizePrefixedHMEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, HMEcuCfgIdentifier(), true); -} - -template -inline bool VerifyHMEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifyBuffer(HMEcuCfgIdentifier()); -} - -template -inline bool VerifySizePrefixedHMEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifySizePrefixedBuffer(HMEcuCfgIdentifier()); -} - -inline const char *HMEcuCfgExtension() { - return "bin"; -} - -inline void FinishHMEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root, HMEcuCfgIdentifier()); -} - -inline void FinishSizePrefixedHMEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root, HMEcuCfgIdentifier()); -} - -} // namespace HMFlatBuffer - -#endif // FLATBUFFERS_GENERATED_HMFLATCFG_HMFLATBUFFER_H_ diff --git a/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg.fbs b/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg.fbs deleted file mode 100644 index 067b96c11..000000000 --- a/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg.fbs +++ /dev/null @@ -1,31 +0,0 @@ -namespace HMCOREFlatBuffer; - -// HMCORE version 3.0 - -file_identifier "BHMR"; -file_extension "bin"; - -table HMCOREEcuCfg { - versionMajor: int (id:0); - versionMinor: int (id:1); - watchdogs: [Watchdog] (id:2); - config: [HmConfig] (id:3); -} - -table Watchdog { - shortName: string (id:0); - deviceFilePath: string (id:1); - maxTimeout: uint32 (id:2); - deactivateOnShutdown: bool (id:3); - hasValueDeactivateOnShutdown: bool (id:4); - requireMagicClose: bool (id:5); - hasValueRequireMagicClose: bool (id:6); -} - -table HmConfig { - periodicity: uint32 (id:0); - bufferSizeMonitor: uint16 (id:1); - bufferSizeAliveSupervision: uint16 (id:2); -} - -root_type HMCOREEcuCfg; diff --git a/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg_generated.h b/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg_generated.h deleted file mode 100644 index d5e9e5b3b..000000000 --- a/score/launch_manager/daemon/src/alive_monitor/config/hmcore_flatcfg_generated.h +++ /dev/null @@ -1,371 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_HMCOREFLATCFG_HMCOREFLATBUFFER_H_ -#define FLATBUFFERS_GENERATED_HMCOREFLATCFG_HMCOREFLATBUFFER_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && - FLATBUFFERS_VERSION_MINOR == 12 && - FLATBUFFERS_VERSION_REVISION == 19, - "Non-compatible flatbuffers version included"); - -namespace HMCOREFlatBuffer { - -struct HMCOREEcuCfg; -struct HMCOREEcuCfgBuilder; - -struct Watchdog; -struct WatchdogBuilder; - -struct HmConfig; -struct HmConfigBuilder; - -struct HMCOREEcuCfg FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HMCOREEcuCfgBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_VERSIONMAJOR = 4, - VT_VERSIONMINOR = 6, - VT_WATCHDOGS = 8, - VT_CONFIG = 10 - }; - int32_t versionMajor() const { - return GetField(VT_VERSIONMAJOR, 0); - } - int32_t versionMinor() const { - return GetField(VT_VERSIONMINOR, 0); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *watchdogs() const { - return GetPointer> *>(VT_WATCHDOGS); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *config() const { - return GetPointer> *>(VT_CONFIG); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_VERSIONMAJOR, 4) && - VerifyField(verifier, VT_VERSIONMINOR, 4) && - VerifyOffset(verifier, VT_WATCHDOGS) && - verifier.VerifyVector(watchdogs()) && - verifier.VerifyVectorOfTables(watchdogs()) && - VerifyOffset(verifier, VT_CONFIG) && - verifier.VerifyVector(config()) && - verifier.VerifyVectorOfTables(config()) && - verifier.EndTable(); - } -}; - -struct HMCOREEcuCfgBuilder { - typedef HMCOREEcuCfg Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_versionMajor(int32_t versionMajor) { - fbb_.AddElement(HMCOREEcuCfg::VT_VERSIONMAJOR, versionMajor, 0); - } - void add_versionMinor(int32_t versionMinor) { - fbb_.AddElement(HMCOREEcuCfg::VT_VERSIONMINOR, versionMinor, 0); - } - void add_watchdogs(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> watchdogs) { - fbb_.AddOffset(HMCOREEcuCfg::VT_WATCHDOGS, watchdogs); - } - void add_config(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> config) { - fbb_.AddOffset(HMCOREEcuCfg::VT_CONFIG, config); - } - explicit HMCOREEcuCfgBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHMCOREEcuCfg( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> watchdogs = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> config = 0) { - HMCOREEcuCfgBuilder builder_(_fbb); - builder_.add_config(config); - builder_.add_watchdogs(watchdogs); - builder_.add_versionMinor(versionMinor); - builder_.add_versionMajor(versionMajor); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateHMCOREEcuCfgDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - const std::vector<::flatbuffers::Offset> *watchdogs = nullptr, - const std::vector<::flatbuffers::Offset> *config = nullptr) { - auto watchdogs__ = watchdogs ? _fbb.CreateVector<::flatbuffers::Offset>(*watchdogs) : 0; - auto config__ = config ? _fbb.CreateVector<::flatbuffers::Offset>(*config) : 0; - return HMCOREFlatBuffer::CreateHMCOREEcuCfg( - _fbb, - versionMajor, - versionMinor, - watchdogs__, - config__); -} - -struct Watchdog FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef WatchdogBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SHORTNAME = 4, - VT_DEVICEFILEPATH = 6, - VT_MAXTIMEOUT = 8, - VT_DEACTIVATEONSHUTDOWN = 10, - VT_HASVALUEDEACTIVATEONSHUTDOWN = 12, - VT_REQUIREMAGICCLOSE = 14, - VT_HASVALUEREQUIREMAGICCLOSE = 16 - }; - const ::flatbuffers::String *shortName() const { - return GetPointer(VT_SHORTNAME); - } - const ::flatbuffers::String *deviceFilePath() const { - return GetPointer(VT_DEVICEFILEPATH); - } - uint32_t maxTimeout() const { - return GetField(VT_MAXTIMEOUT, 0); - } - bool deactivateOnShutdown() const { - return GetField(VT_DEACTIVATEONSHUTDOWN, 0) != 0; - } - bool hasValueDeactivateOnShutdown() const { - return GetField(VT_HASVALUEDEACTIVATEONSHUTDOWN, 0) != 0; - } - bool requireMagicClose() const { - return GetField(VT_REQUIREMAGICCLOSE, 0) != 0; - } - bool hasValueRequireMagicClose() const { - return GetField(VT_HASVALUEREQUIREMAGICCLOSE, 0) != 0; - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SHORTNAME) && - verifier.VerifyString(shortName()) && - VerifyOffset(verifier, VT_DEVICEFILEPATH) && - verifier.VerifyString(deviceFilePath()) && - VerifyField(verifier, VT_MAXTIMEOUT, 4) && - VerifyField(verifier, VT_DEACTIVATEONSHUTDOWN, 1) && - VerifyField(verifier, VT_HASVALUEDEACTIVATEONSHUTDOWN, 1) && - VerifyField(verifier, VT_REQUIREMAGICCLOSE, 1) && - VerifyField(verifier, VT_HASVALUEREQUIREMAGICCLOSE, 1) && - verifier.EndTable(); - } -}; - -struct WatchdogBuilder { - typedef Watchdog Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_shortName(::flatbuffers::Offset<::flatbuffers::String> shortName) { - fbb_.AddOffset(Watchdog::VT_SHORTNAME, shortName); - } - void add_deviceFilePath(::flatbuffers::Offset<::flatbuffers::String> deviceFilePath) { - fbb_.AddOffset(Watchdog::VT_DEVICEFILEPATH, deviceFilePath); - } - void add_maxTimeout(uint32_t maxTimeout) { - fbb_.AddElement(Watchdog::VT_MAXTIMEOUT, maxTimeout, 0); - } - void add_deactivateOnShutdown(bool deactivateOnShutdown) { - fbb_.AddElement(Watchdog::VT_DEACTIVATEONSHUTDOWN, static_cast(deactivateOnShutdown), 0); - } - void add_hasValueDeactivateOnShutdown(bool hasValueDeactivateOnShutdown) { - fbb_.AddElement(Watchdog::VT_HASVALUEDEACTIVATEONSHUTDOWN, static_cast(hasValueDeactivateOnShutdown), 0); - } - void add_requireMagicClose(bool requireMagicClose) { - fbb_.AddElement(Watchdog::VT_REQUIREMAGICCLOSE, static_cast(requireMagicClose), 0); - } - void add_hasValueRequireMagicClose(bool hasValueRequireMagicClose) { - fbb_.AddElement(Watchdog::VT_HASVALUEREQUIREMAGICCLOSE, static_cast(hasValueRequireMagicClose), 0); - } - explicit WatchdogBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateWatchdog( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> shortName = 0, - ::flatbuffers::Offset<::flatbuffers::String> deviceFilePath = 0, - uint32_t maxTimeout = 0, - bool deactivateOnShutdown = false, - bool hasValueDeactivateOnShutdown = false, - bool requireMagicClose = false, - bool hasValueRequireMagicClose = false) { - WatchdogBuilder builder_(_fbb); - builder_.add_maxTimeout(maxTimeout); - builder_.add_deviceFilePath(deviceFilePath); - builder_.add_shortName(shortName); - builder_.add_hasValueRequireMagicClose(hasValueRequireMagicClose); - builder_.add_requireMagicClose(requireMagicClose); - builder_.add_hasValueDeactivateOnShutdown(hasValueDeactivateOnShutdown); - builder_.add_deactivateOnShutdown(deactivateOnShutdown); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateWatchdogDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *shortName = nullptr, - const char *deviceFilePath = nullptr, - uint32_t maxTimeout = 0, - bool deactivateOnShutdown = false, - bool hasValueDeactivateOnShutdown = false, - bool requireMagicClose = false, - bool hasValueRequireMagicClose = false) { - auto shortName__ = shortName ? _fbb.CreateString(shortName) : 0; - auto deviceFilePath__ = deviceFilePath ? _fbb.CreateString(deviceFilePath) : 0; - return HMCOREFlatBuffer::CreateWatchdog( - _fbb, - shortName__, - deviceFilePath__, - maxTimeout, - deactivateOnShutdown, - hasValueDeactivateOnShutdown, - requireMagicClose, - hasValueRequireMagicClose); -} - -struct HmConfig FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef HmConfigBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_PERIODICITY = 4, - VT_BUFFERSIZEMONITOR = 6, - VT_BUFFERSIZEALIVESUPERVISION = 8 - }; - uint32_t periodicity() const { - return GetField(VT_PERIODICITY, 0); - } - uint16_t bufferSizeMonitor() const { - return GetField(VT_BUFFERSIZEMONITOR, 0); - } - uint16_t bufferSizeAliveSupervision() const { - return GetField(VT_BUFFERSIZEALIVESUPERVISION, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_PERIODICITY, 4) && - VerifyField(verifier, VT_BUFFERSIZEMONITOR, 2) && - VerifyField(verifier, VT_BUFFERSIZEALIVESUPERVISION, 2) && - verifier.EndTable(); - } -}; - -struct HmConfigBuilder { - typedef HmConfig Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_periodicity(uint32_t periodicity) { - fbb_.AddElement(HmConfig::VT_PERIODICITY, periodicity, 0); - } - void add_bufferSizeMonitor(uint16_t bufferSizeMonitor) { - fbb_.AddElement(HmConfig::VT_BUFFERSIZEMONITOR, bufferSizeMonitor, 0); - } - void add_bufferSizeAliveSupervision(uint16_t bufferSizeAliveSupervision) { - fbb_.AddElement(HmConfig::VT_BUFFERSIZEALIVESUPERVISION, bufferSizeAliveSupervision, 0); - } - explicit HmConfigBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateHmConfig( - ::flatbuffers::FlatBufferBuilder &_fbb, - uint32_t periodicity = 0, - uint16_t bufferSizeMonitor = 0, - uint16_t bufferSizeAliveSupervision = 0) { - HmConfigBuilder builder_(_fbb); - builder_.add_periodicity(periodicity); - builder_.add_bufferSizeAliveSupervision(bufferSizeAliveSupervision); - builder_.add_bufferSizeMonitor(bufferSizeMonitor); - return builder_.Finish(); -} - -inline const HMCOREFlatBuffer::HMCOREEcuCfg *GetHMCOREEcuCfg(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const HMCOREFlatBuffer::HMCOREEcuCfg *GetSizePrefixedHMCOREEcuCfg(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline const char *HMCOREEcuCfgIdentifier() { - return "BHMR"; -} - -inline bool HMCOREEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, HMCOREEcuCfgIdentifier()); -} - -inline bool SizePrefixedHMCOREEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, HMCOREEcuCfgIdentifier(), true); -} - -template -inline bool VerifyHMCOREEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifyBuffer(HMCOREEcuCfgIdentifier()); -} - -template -inline bool VerifySizePrefixedHMCOREEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifySizePrefixedBuffer(HMCOREEcuCfgIdentifier()); -} - -inline const char *HMCOREEcuCfgExtension() { - return "bin"; -} - -inline void FinishHMCOREEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root, HMCOREEcuCfgIdentifier()); -} - -inline void FinishSizePrefixedHMCOREEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root, HMCOREEcuCfgIdentifier()); -} - -} // namespace HMCOREFlatBuffer - -#endif // FLATBUFFERS_GENERATED_HMCOREFLATCFG_HMCOREFLATBUFFER_H_ diff --git a/score/launch_manager/daemon/src/alive_monitor/details/BUILD b/score/launch_manager/daemon/src/alive_monitor/details/BUILD index 686d49b18..305620b1a 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/details/BUILD @@ -30,7 +30,6 @@ cc_library( visibility = ["//score/launch_manager/daemon/src/alive_monitor:__subpackages__"], deps = [ "//score/launch_manager/daemon/src/alive_monitor:alive_monitor_h", - "//score/launch_manager/daemon/src/alive_monitor:config", "//score/launch_manager/daemon/src/alive_monitor/details/ifappl:data_structures", "//score/launch_manager/daemon/src/alive_monitor/details/ipc:ipc_if", "//score/launch_manager/daemon/src/alive_monitor/details/logging:phm_logging", diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp index de9048508..b2fa8c5a8 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.cpp @@ -18,30 +18,29 @@ #include "score/mw/launch_manager/alive_monitor/details/daemon/AliveMonitorImpl.hpp" #include "score/mw/launch_manager/alive_monitor/details/logging/PhmLogger.hpp" #include "score/mw/launch_manager/alive_monitor/details/watchdog/WatchdogImpl.hpp" -#include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" namespace score { namespace lcm { namespace saf { namespace daemon { -AliveMonitorImpl::AliveMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog, std::unique_ptr process_state_receiver) - : m_recovery_client(recovery_client), m_watchdog(std::move(watchdog)), m_logger{score::lcm::saf::logging::PhmLogger::getLogger(score::lcm::saf::logging::PhmLogger::EContext::factory)}, m_process_state_receiver{std::move(process_state_receiver)} {} +AliveMonitorImpl::AliveMonitorImpl(std::shared_ptr recovery_client, + std::unique_ptr watchdog, + std::unique_ptr process_state_receiver, + const score::mw::launch_manager::configuration::Config& config) + : m_recovery_client(recovery_client), + m_watchdog(std::move(watchdog)), + m_logger{score::lcm::saf::logging::PhmLogger::getLogger(score::lcm::saf::logging::PhmLogger::EContext::factory)}, + m_process_state_receiver{std::move(process_state_receiver)}, + m_config{config} {} EInitCode AliveMonitorImpl::init() noexcept { score::lcm::saf::daemon::EInitCode initResult{score::lcm::saf::daemon::EInitCode::kGeneralError}; try { m_osClock.startMeasurement(); - score::mw::launch_manager::configuration::FlatbufferConfigLoader loader; - auto config_result = loader.load("etc/launch_manager_config.bin"); - if (!config_result.has_value()) { - m_logger.LogError() << "HealthMonitor: Failed to load launch_manager_config.bin"; - return EInitCode::kGeneralError; - } - m_daemon = std::make_unique(m_osClock, m_logger, std::move(m_watchdog), std::move(m_process_state_receiver)); - initResult = m_daemon->init(m_recovery_client, *config_result); + initResult = m_daemon->init(m_recovery_client, m_config); if (initResult == score::lcm::saf::daemon::EInitCode::kNoError) { const long ms{m_osClock.endMeasurement()}; diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp index 3f8a83603..d45e9127d 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/AliveMonitorImpl.hpp @@ -17,6 +17,7 @@ #include #include "score/mw/launch_manager/alive_monitor/details/daemon/IAliveMonitor.hpp" +#include "score/mw/launch_manager/configuration/config.hpp" namespace score { namespace lcm { @@ -33,7 +34,10 @@ namespace daemon { class AliveMonitorImpl : public IAliveMonitor { public: - AliveMonitorImpl(std::shared_ptr recovery_client, std::unique_ptr watchdog, std::unique_ptr process_state_receiver); + AliveMonitorImpl(std::shared_ptr recovery_client, + std::unique_ptr watchdog, + std::unique_ptr process_state_receiver, + const score::mw::launch_manager::configuration::Config& config); EInitCode init() noexcept override; @@ -46,6 +50,7 @@ class AliveMonitorImpl : public IAliveMonitor { std::unique_ptr m_daemon{nullptr}; score::lcm::saf::timers::OsClockInterface m_osClock{}; std::unique_ptr m_process_state_receiver; + const score::mw::launch_manager::configuration::Config& m_config; }; } // namespace daemon diff --git a/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD b/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD index 82149e336..bfcbcf24d 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/details/daemon/BUILD @@ -88,6 +88,6 @@ cc_library( ":i_health_monitor", "//score/launch_manager/daemon/src/alive_monitor/details/logging:phm_logging", "//score/launch_manager/daemon/src/alive_monitor/details/watchdog:watchdog_impl", - "//score/launch_manager/daemon/src/configuration:flatbuffer_config_loader", + "//score/launch_manager/daemon/src/configuration:config", ], ) diff --git a/score/launch_manager/daemon/src/configuration/BUILD b/score/launch_manager/daemon/src/configuration/BUILD index 6c0174a83..e7ead9d0d 100644 --- a/score/launch_manager/daemon/src/configuration/BUILD +++ b/score/launch_manager/daemon/src/configuration/BUILD @@ -13,17 +13,6 @@ load("@rules_cc//cc:defs.bzl", "cc_library") load("@score_baselibs//score/flatbuffers/bazel:codegen.bzl", "generate_cpp") -exports_files([ - "lm_flatcfg.fbs", - "lm_flatcfg_generated.h", -]) - -filegroup( - name = "lm_flatcfg_fbs", - srcs = ["lm_flatcfg.fbs"], - visibility = ["//visibility:public"], -) - filegroup( name = "new_lm_flatcfg_fbs", srcs = ["details/new_lm_flatcfg.fbs"], @@ -124,15 +113,6 @@ cc_test( ], ) -cc_library( - name = "lm_flatcfg", - hdrs = ["lm_flatcfg_generated.h"], - include_prefix = "score/mw/launch_manager/configuration", - strip_include_prefix = "/score/launch_manager/daemon/src/configuration", - visibility = ["//score:__subpackages__"], - deps = ["@flatbuffers"], -) - cc_library( name = "configuration_adapter", srcs = ["configuration_adapter.cpp"], diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp index 644fe3a3f..9b6f13b48 100644 --- a/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp @@ -12,7 +12,6 @@ ********************************************************************************/ #include "score/mw/launch_manager/configuration/configuration_adapter.hpp" -#include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" #include "score/mw/launch_manager/common/log.hpp" #include "score/mw/launch_manager/osal/num_cores.hpp" @@ -46,7 +45,7 @@ score::lcm::internal::osal::CommsType ConfigurationAdapter::mapApplicationType( } } -bool ConfigurationAdapter::initialize() { +bool ConfigurationAdapter::initialize(const Config& config) { LM_LOG_DEBUG() << "Loading LCM Configurations..."; const char* env_val = getenv("ECUCFG_ENV_VAR_ROOTFOLDER"); @@ -55,14 +54,7 @@ bool ConfigurationAdapter::initialize() { } LM_LOG_DEBUG() << "ECUCFG_ENV_VAR_ROOTFOLDER set successfully"; - FlatbufferConfigLoader loader; - auto result = loader.load("etc/launch_manager_config.bin"); - if (!result.has_value()) { - LM_LOG_ERROR() << "Failed to load launch_manager_config.bin"; - return false; - } - - return buildFromConfig(std::move(*result)); + return buildFromConfig(config); } void ConfigurationAdapter::deinitialize() { @@ -82,7 +74,7 @@ void ConfigurationAdapter::deinitialize() { } } -bool ConfigurationAdapter::buildFromConfig(Config config) { +bool ConfigurationAdapter::buildFromConfig(const Config& config) { const std::string initial_run_target_name = std::string(config.initialRunTarget()); ProcessGroup pg; diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp index ff1347b19..941321845 100644 --- a/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp @@ -19,7 +19,6 @@ #include #include #include "score/mw/launch_manager/configuration/config.hpp" -#include "score/mw/launch_manager/configuration/config_loader.hpp" #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/common/constants.hpp" #include "score/mw/launch_manager/common/process_group_state_id.hpp" @@ -68,9 +67,15 @@ struct ProcessGroup final { std::vector processes_; }; +/// @brief Temporary bridge that translates the new Config model (RunTargets, Components) into the +/// legacy API (ProcessGroups, ProcessGroupStates, OsProcess) consumed by ProcessGroupManager, Graph, +/// and related code. It exists only to decouple the config-format migration from the broader code +/// migration and should be removed once ProcessGroupManager and its dependents are adapted to work +/// directly with RunTarget/Component concepts. class ConfigurationAdapter final { public: - bool initialize(); + /// @brief Initialize from a pre-loaded Config object (preferred — avoids a second file read). + bool initialize(const Config& config); void deinitialize(); std::optional*> getListOfProcessGroups() const; @@ -93,7 +98,7 @@ class ConfigurationAdapter final { static const int32_t kDefaultNormalSchedulingPriority; private: - bool buildFromConfig(Config config); + bool buildFromConfig(const Config& config); score::lcm::internal::osal::CommsType mapApplicationType(ApplicationType app_type) const; diff --git a/score/launch_manager/daemon/src/configuration/lm_flatcfg.fbs b/score/launch_manager/daemon/src/configuration/lm_flatcfg.fbs deleted file mode 100644 index 23e678bbf..000000000 --- a/score/launch_manager/daemon/src/configuration/lm_flatcfg.fbs +++ /dev/null @@ -1,90 +0,0 @@ -namespace LMFlatBuffer; - -// LM version 7.0 - -file_identifier "BLMR"; -file_extension "bin"; - -enum ExecutionStateReportingBehaviorEnum : byte { - ReportsExecutionState = 0, // REPORTS-EXECUTION-STATE - DoesNotReportExecutionState = 1 // DOES-NOT-REPORT-EXECUTION-STATE -} - -enum TerminationBehaviorEnum : byte { - ProcessIsNotSelfTerminating = 0, // PROCESS-IS-NOT-SELF-TERMINATING - ProcessIsSelfTerminating = 1 // PROCESS-IS-SELF-TERMINATING -} - -table LMEcuCfg { - versionMajor: int (id:0); - versionMinor: int (id:1); - ModeGroup: [ModeGroup] (id:2); - Process: [Process] (id:3); -} - -table ModeGroup { - identifier: string (id:0); - initialMode_name: string (id:1); - initialMode_value: string (id:2); - recoveryMode_name: string (id:3); - modeDeclaration: [ModeDeclaration] (id:4); -} - -// TODO: Could be moved into ModeGroup -table ModeDeclaration { - identifier: string (id:0); -} - -table Process { - identifier: string (id:0); - numberOfRestartAttempts: uint (id:1); - functionClusterAffiliation: string (id:2); - coremask: string (id:3); - uid: uint (id:4); - gid: uint (id:5); - path: string (id:6); - securityPolicyDetails: string (id:7); - executable_reportingBehavior: ExecutionStateReportingBehaviorEnum (id:8); - startupConfig: [ProcessStartupConfig] (id:9); - sgids: [ProcessSgid] (id:10); -} - -table ProcessStartupConfig { - identifier: string (id:0); - enterTimeoutValue: uint (id:1); - exitTimeoutValue: uint (id:2); - schedulingPriority: string (id:3); - schedulingPolicy: string (id:4); - executionError: string (id:5); - terminationBehavior: TerminationBehaviorEnum (id:6); - executionDependency: [ProcessExecutionDependency] (id:7); - processGroupStateDependency: [ProcessGroupStateDependency] (id:8); - environmentVariable: [EnvironmentVariable] (id:9); - processArgument: [ProcessArgument] (id:10); - memoryUsage: uint64 (id:11); -} - -table ProcessGroupStateDependency { - stateMachine_name: string (id:0); - stateName: string (id:1); -} - -table ProcessExecutionDependency { - stateName: string (id:0); - targetProcess_identifier: string (id:1); -} - -table EnvironmentVariable { - key: string (id:0); - value: string (id:1); -} - -table ProcessArgument { - argument: string (id:0); -} - -table ProcessSgid { - sgid: uint (id:0); -} - -root_type LMEcuCfg; diff --git a/score/launch_manager/daemon/src/configuration/lm_flatcfg_generated.h b/score/launch_manager/daemon/src/configuration/lm_flatcfg_generated.h deleted file mode 100644 index 83ed21465..000000000 --- a/score/launch_manager/daemon/src/configuration/lm_flatcfg_generated.h +++ /dev/null @@ -1,1105 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2026 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_LMFLATCFG_LMFLATBUFFER_H_ -#define FLATBUFFERS_GENERATED_LMFLATCFG_LMFLATBUFFER_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 25 && - FLATBUFFERS_VERSION_MINOR == 12 && - FLATBUFFERS_VERSION_REVISION == 19, - "Non-compatible flatbuffers version included"); - -namespace LMFlatBuffer { - -struct LMEcuCfg; -struct LMEcuCfgBuilder; - -struct ModeGroup; -struct ModeGroupBuilder; - -struct ModeDeclaration; -struct ModeDeclarationBuilder; - -struct Process; -struct ProcessBuilder; - -struct ProcessStartupConfig; -struct ProcessStartupConfigBuilder; - -struct ProcessGroupStateDependency; -struct ProcessGroupStateDependencyBuilder; - -struct ProcessExecutionDependency; -struct ProcessExecutionDependencyBuilder; - -struct EnvironmentVariable; -struct EnvironmentVariableBuilder; - -struct ProcessArgument; -struct ProcessArgumentBuilder; - -struct ProcessSgid; -struct ProcessSgidBuilder; - -enum ExecutionStateReportingBehaviorEnum : int8_t { - ExecutionStateReportingBehaviorEnum_ReportsExecutionState = 0, - ExecutionStateReportingBehaviorEnum_DoesNotReportExecutionState = 1, - ExecutionStateReportingBehaviorEnum_MIN = ExecutionStateReportingBehaviorEnum_ReportsExecutionState, - ExecutionStateReportingBehaviorEnum_MAX = ExecutionStateReportingBehaviorEnum_DoesNotReportExecutionState -}; - -inline const ExecutionStateReportingBehaviorEnum (&EnumValuesExecutionStateReportingBehaviorEnum())[2] { - static const ExecutionStateReportingBehaviorEnum values[] = { - ExecutionStateReportingBehaviorEnum_ReportsExecutionState, - ExecutionStateReportingBehaviorEnum_DoesNotReportExecutionState - }; - return values; -} - -inline const char * const *EnumNamesExecutionStateReportingBehaviorEnum() { - static const char * const names[3] = { - "ReportsExecutionState", - "DoesNotReportExecutionState", - nullptr - }; - return names; -} - -inline const char *EnumNameExecutionStateReportingBehaviorEnum(ExecutionStateReportingBehaviorEnum e) { - if (::flatbuffers::IsOutRange(e, ExecutionStateReportingBehaviorEnum_ReportsExecutionState, ExecutionStateReportingBehaviorEnum_DoesNotReportExecutionState)) return ""; - const size_t index = static_cast(e); - return EnumNamesExecutionStateReportingBehaviorEnum()[index]; -} - -enum TerminationBehaviorEnum : int8_t { - TerminationBehaviorEnum_ProcessIsNotSelfTerminating = 0, - TerminationBehaviorEnum_ProcessIsSelfTerminating = 1, - TerminationBehaviorEnum_MIN = TerminationBehaviorEnum_ProcessIsNotSelfTerminating, - TerminationBehaviorEnum_MAX = TerminationBehaviorEnum_ProcessIsSelfTerminating -}; - -inline const TerminationBehaviorEnum (&EnumValuesTerminationBehaviorEnum())[2] { - static const TerminationBehaviorEnum values[] = { - TerminationBehaviorEnum_ProcessIsNotSelfTerminating, - TerminationBehaviorEnum_ProcessIsSelfTerminating - }; - return values; -} - -inline const char * const *EnumNamesTerminationBehaviorEnum() { - static const char * const names[3] = { - "ProcessIsNotSelfTerminating", - "ProcessIsSelfTerminating", - nullptr - }; - return names; -} - -inline const char *EnumNameTerminationBehaviorEnum(TerminationBehaviorEnum e) { - if (::flatbuffers::IsOutRange(e, TerminationBehaviorEnum_ProcessIsNotSelfTerminating, TerminationBehaviorEnum_ProcessIsSelfTerminating)) return ""; - const size_t index = static_cast(e); - return EnumNamesTerminationBehaviorEnum()[index]; -} - -struct LMEcuCfg FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef LMEcuCfgBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_VERSIONMAJOR = 4, - VT_VERSIONMINOR = 6, - VT_MODEGROUP = 8, - VT_PROCESS = 10 - }; - int32_t versionMajor() const { - return GetField(VT_VERSIONMAJOR, 0); - } - int32_t versionMinor() const { - return GetField(VT_VERSIONMINOR, 0); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *ModeGroup() const { - return GetPointer> *>(VT_MODEGROUP); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *Process() const { - return GetPointer> *>(VT_PROCESS); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_VERSIONMAJOR, 4) && - VerifyField(verifier, VT_VERSIONMINOR, 4) && - VerifyOffset(verifier, VT_MODEGROUP) && - verifier.VerifyVector(ModeGroup()) && - verifier.VerifyVectorOfTables(ModeGroup()) && - VerifyOffset(verifier, VT_PROCESS) && - verifier.VerifyVector(Process()) && - verifier.VerifyVectorOfTables(Process()) && - verifier.EndTable(); - } -}; - -struct LMEcuCfgBuilder { - typedef LMEcuCfg Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_versionMajor(int32_t versionMajor) { - fbb_.AddElement(LMEcuCfg::VT_VERSIONMAJOR, versionMajor, 0); - } - void add_versionMinor(int32_t versionMinor) { - fbb_.AddElement(LMEcuCfg::VT_VERSIONMINOR, versionMinor, 0); - } - void add_ModeGroup(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> ModeGroup) { - fbb_.AddOffset(LMEcuCfg::VT_MODEGROUP, ModeGroup); - } - void add_Process(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> Process) { - fbb_.AddOffset(LMEcuCfg::VT_PROCESS, Process); - } - explicit LMEcuCfgBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateLMEcuCfg( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> ModeGroup = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> Process = 0) { - LMEcuCfgBuilder builder_(_fbb); - builder_.add_Process(Process); - builder_.add_ModeGroup(ModeGroup); - builder_.add_versionMinor(versionMinor); - builder_.add_versionMajor(versionMajor); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateLMEcuCfgDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int32_t versionMajor = 0, - int32_t versionMinor = 0, - const std::vector<::flatbuffers::Offset> *ModeGroup = nullptr, - const std::vector<::flatbuffers::Offset> *Process = nullptr) { - auto ModeGroup__ = ModeGroup ? _fbb.CreateVector<::flatbuffers::Offset>(*ModeGroup) : 0; - auto Process__ = Process ? _fbb.CreateVector<::flatbuffers::Offset>(*Process) : 0; - return LMFlatBuffer::CreateLMEcuCfg( - _fbb, - versionMajor, - versionMinor, - ModeGroup__, - Process__); -} - -struct ModeGroup FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ModeGroupBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_IDENTIFIER = 4, - VT_INITIALMODE_NAME = 6, - VT_INITIALMODE_VALUE = 8, - VT_RECOVERYMODE_NAME = 10, - VT_MODEDECLARATION = 12 - }; - const ::flatbuffers::String *identifier() const { - return GetPointer(VT_IDENTIFIER); - } - const ::flatbuffers::String *initialMode_name() const { - return GetPointer(VT_INITIALMODE_NAME); - } - const ::flatbuffers::String *initialMode_value() const { - return GetPointer(VT_INITIALMODE_VALUE); - } - const ::flatbuffers::String *recoveryMode_name() const { - return GetPointer(VT_RECOVERYMODE_NAME); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *modeDeclaration() const { - return GetPointer> *>(VT_MODEDECLARATION); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_IDENTIFIER) && - verifier.VerifyString(identifier()) && - VerifyOffset(verifier, VT_INITIALMODE_NAME) && - verifier.VerifyString(initialMode_name()) && - VerifyOffset(verifier, VT_INITIALMODE_VALUE) && - verifier.VerifyString(initialMode_value()) && - VerifyOffset(verifier, VT_RECOVERYMODE_NAME) && - verifier.VerifyString(recoveryMode_name()) && - VerifyOffset(verifier, VT_MODEDECLARATION) && - verifier.VerifyVector(modeDeclaration()) && - verifier.VerifyVectorOfTables(modeDeclaration()) && - verifier.EndTable(); - } -}; - -struct ModeGroupBuilder { - typedef ModeGroup Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_identifier(::flatbuffers::Offset<::flatbuffers::String> identifier) { - fbb_.AddOffset(ModeGroup::VT_IDENTIFIER, identifier); - } - void add_initialMode_name(::flatbuffers::Offset<::flatbuffers::String> initialMode_name) { - fbb_.AddOffset(ModeGroup::VT_INITIALMODE_NAME, initialMode_name); - } - void add_initialMode_value(::flatbuffers::Offset<::flatbuffers::String> initialMode_value) { - fbb_.AddOffset(ModeGroup::VT_INITIALMODE_VALUE, initialMode_value); - } - void add_recoveryMode_name(::flatbuffers::Offset<::flatbuffers::String> recoveryMode_name) { - fbb_.AddOffset(ModeGroup::VT_RECOVERYMODE_NAME, recoveryMode_name); - } - void add_modeDeclaration(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> modeDeclaration) { - fbb_.AddOffset(ModeGroup::VT_MODEDECLARATION, modeDeclaration); - } - explicit ModeGroupBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateModeGroup( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> identifier = 0, - ::flatbuffers::Offset<::flatbuffers::String> initialMode_name = 0, - ::flatbuffers::Offset<::flatbuffers::String> initialMode_value = 0, - ::flatbuffers::Offset<::flatbuffers::String> recoveryMode_name = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> modeDeclaration = 0) { - ModeGroupBuilder builder_(_fbb); - builder_.add_modeDeclaration(modeDeclaration); - builder_.add_recoveryMode_name(recoveryMode_name); - builder_.add_initialMode_value(initialMode_value); - builder_.add_initialMode_name(initialMode_name); - builder_.add_identifier(identifier); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateModeGroupDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *identifier = nullptr, - const char *initialMode_name = nullptr, - const char *initialMode_value = nullptr, - const char *recoveryMode_name = nullptr, - const std::vector<::flatbuffers::Offset> *modeDeclaration = nullptr) { - auto identifier__ = identifier ? _fbb.CreateString(identifier) : 0; - auto initialMode_name__ = initialMode_name ? _fbb.CreateString(initialMode_name) : 0; - auto initialMode_value__ = initialMode_value ? _fbb.CreateString(initialMode_value) : 0; - auto recoveryMode_name__ = recoveryMode_name ? _fbb.CreateString(recoveryMode_name) : 0; - auto modeDeclaration__ = modeDeclaration ? _fbb.CreateVector<::flatbuffers::Offset>(*modeDeclaration) : 0; - return LMFlatBuffer::CreateModeGroup( - _fbb, - identifier__, - initialMode_name__, - initialMode_value__, - recoveryMode_name__, - modeDeclaration__); -} - -struct ModeDeclaration FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ModeDeclarationBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_IDENTIFIER = 4 - }; - const ::flatbuffers::String *identifier() const { - return GetPointer(VT_IDENTIFIER); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_IDENTIFIER) && - verifier.VerifyString(identifier()) && - verifier.EndTable(); - } -}; - -struct ModeDeclarationBuilder { - typedef ModeDeclaration Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_identifier(::flatbuffers::Offset<::flatbuffers::String> identifier) { - fbb_.AddOffset(ModeDeclaration::VT_IDENTIFIER, identifier); - } - explicit ModeDeclarationBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateModeDeclaration( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> identifier = 0) { - ModeDeclarationBuilder builder_(_fbb); - builder_.add_identifier(identifier); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateModeDeclarationDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *identifier = nullptr) { - auto identifier__ = identifier ? _fbb.CreateString(identifier) : 0; - return LMFlatBuffer::CreateModeDeclaration( - _fbb, - identifier__); -} - -struct Process FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_IDENTIFIER = 4, - VT_NUMBEROFRESTARTATTEMPTS = 6, - VT_FUNCTIONCLUSTERAFFILIATION = 8, - VT_COREMASK = 10, - VT_UID = 12, - VT_GID = 14, - VT_PATH = 16, - VT_SECURITYPOLICYDETAILS = 18, - VT_EXECUTABLE_REPORTINGBEHAVIOR = 20, - VT_STARTUPCONFIG = 22, - VT_SGIDS = 24 - }; - const ::flatbuffers::String *identifier() const { - return GetPointer(VT_IDENTIFIER); - } - uint32_t numberOfRestartAttempts() const { - return GetField(VT_NUMBEROFRESTARTATTEMPTS, 0); - } - const ::flatbuffers::String *functionClusterAffiliation() const { - return GetPointer(VT_FUNCTIONCLUSTERAFFILIATION); - } - const ::flatbuffers::String *coremask() const { - return GetPointer(VT_COREMASK); - } - uint32_t uid() const { - return GetField(VT_UID, 0); - } - uint32_t gid() const { - return GetField(VT_GID, 0); - } - const ::flatbuffers::String *path() const { - return GetPointer(VT_PATH); - } - const ::flatbuffers::String *securityPolicyDetails() const { - return GetPointer(VT_SECURITYPOLICYDETAILS); - } - LMFlatBuffer::ExecutionStateReportingBehaviorEnum executable_reportingBehavior() const { - return static_cast(GetField(VT_EXECUTABLE_REPORTINGBEHAVIOR, 0)); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *startupConfig() const { - return GetPointer> *>(VT_STARTUPCONFIG); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *sgids() const { - return GetPointer> *>(VT_SGIDS); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_IDENTIFIER) && - verifier.VerifyString(identifier()) && - VerifyField(verifier, VT_NUMBEROFRESTARTATTEMPTS, 4) && - VerifyOffset(verifier, VT_FUNCTIONCLUSTERAFFILIATION) && - verifier.VerifyString(functionClusterAffiliation()) && - VerifyOffset(verifier, VT_COREMASK) && - verifier.VerifyString(coremask()) && - VerifyField(verifier, VT_UID, 4) && - VerifyField(verifier, VT_GID, 4) && - VerifyOffset(verifier, VT_PATH) && - verifier.VerifyString(path()) && - VerifyOffset(verifier, VT_SECURITYPOLICYDETAILS) && - verifier.VerifyString(securityPolicyDetails()) && - VerifyField(verifier, VT_EXECUTABLE_REPORTINGBEHAVIOR, 1) && - VerifyOffset(verifier, VT_STARTUPCONFIG) && - verifier.VerifyVector(startupConfig()) && - verifier.VerifyVectorOfTables(startupConfig()) && - VerifyOffset(verifier, VT_SGIDS) && - verifier.VerifyVector(sgids()) && - verifier.VerifyVectorOfTables(sgids()) && - verifier.EndTable(); - } -}; - -struct ProcessBuilder { - typedef Process Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_identifier(::flatbuffers::Offset<::flatbuffers::String> identifier) { - fbb_.AddOffset(Process::VT_IDENTIFIER, identifier); - } - void add_numberOfRestartAttempts(uint32_t numberOfRestartAttempts) { - fbb_.AddElement(Process::VT_NUMBEROFRESTARTATTEMPTS, numberOfRestartAttempts, 0); - } - void add_functionClusterAffiliation(::flatbuffers::Offset<::flatbuffers::String> functionClusterAffiliation) { - fbb_.AddOffset(Process::VT_FUNCTIONCLUSTERAFFILIATION, functionClusterAffiliation); - } - void add_coremask(::flatbuffers::Offset<::flatbuffers::String> coremask) { - fbb_.AddOffset(Process::VT_COREMASK, coremask); - } - void add_uid(uint32_t uid) { - fbb_.AddElement(Process::VT_UID, uid, 0); - } - void add_gid(uint32_t gid) { - fbb_.AddElement(Process::VT_GID, gid, 0); - } - void add_path(::flatbuffers::Offset<::flatbuffers::String> path) { - fbb_.AddOffset(Process::VT_PATH, path); - } - void add_securityPolicyDetails(::flatbuffers::Offset<::flatbuffers::String> securityPolicyDetails) { - fbb_.AddOffset(Process::VT_SECURITYPOLICYDETAILS, securityPolicyDetails); - } - void add_executable_reportingBehavior(LMFlatBuffer::ExecutionStateReportingBehaviorEnum executable_reportingBehavior) { - fbb_.AddElement(Process::VT_EXECUTABLE_REPORTINGBEHAVIOR, static_cast(executable_reportingBehavior), 0); - } - void add_startupConfig(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> startupConfig) { - fbb_.AddOffset(Process::VT_STARTUPCONFIG, startupConfig); - } - void add_sgids(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> sgids) { - fbb_.AddOffset(Process::VT_SGIDS, sgids); - } - explicit ProcessBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcess( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> identifier = 0, - uint32_t numberOfRestartAttempts = 0, - ::flatbuffers::Offset<::flatbuffers::String> functionClusterAffiliation = 0, - ::flatbuffers::Offset<::flatbuffers::String> coremask = 0, - uint32_t uid = 0, - uint32_t gid = 0, - ::flatbuffers::Offset<::flatbuffers::String> path = 0, - ::flatbuffers::Offset<::flatbuffers::String> securityPolicyDetails = 0, - LMFlatBuffer::ExecutionStateReportingBehaviorEnum executable_reportingBehavior = LMFlatBuffer::ExecutionStateReportingBehaviorEnum_ReportsExecutionState, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> startupConfig = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> sgids = 0) { - ProcessBuilder builder_(_fbb); - builder_.add_sgids(sgids); - builder_.add_startupConfig(startupConfig); - builder_.add_securityPolicyDetails(securityPolicyDetails); - builder_.add_path(path); - builder_.add_gid(gid); - builder_.add_uid(uid); - builder_.add_coremask(coremask); - builder_.add_functionClusterAffiliation(functionClusterAffiliation); - builder_.add_numberOfRestartAttempts(numberOfRestartAttempts); - builder_.add_identifier(identifier); - builder_.add_executable_reportingBehavior(executable_reportingBehavior); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *identifier = nullptr, - uint32_t numberOfRestartAttempts = 0, - const char *functionClusterAffiliation = nullptr, - const char *coremask = nullptr, - uint32_t uid = 0, - uint32_t gid = 0, - const char *path = nullptr, - const char *securityPolicyDetails = nullptr, - LMFlatBuffer::ExecutionStateReportingBehaviorEnum executable_reportingBehavior = LMFlatBuffer::ExecutionStateReportingBehaviorEnum_ReportsExecutionState, - const std::vector<::flatbuffers::Offset> *startupConfig = nullptr, - const std::vector<::flatbuffers::Offset> *sgids = nullptr) { - auto identifier__ = identifier ? _fbb.CreateString(identifier) : 0; - auto functionClusterAffiliation__ = functionClusterAffiliation ? _fbb.CreateString(functionClusterAffiliation) : 0; - auto coremask__ = coremask ? _fbb.CreateString(coremask) : 0; - auto path__ = path ? _fbb.CreateString(path) : 0; - auto securityPolicyDetails__ = securityPolicyDetails ? _fbb.CreateString(securityPolicyDetails) : 0; - auto startupConfig__ = startupConfig ? _fbb.CreateVector<::flatbuffers::Offset>(*startupConfig) : 0; - auto sgids__ = sgids ? _fbb.CreateVector<::flatbuffers::Offset>(*sgids) : 0; - return LMFlatBuffer::CreateProcess( - _fbb, - identifier__, - numberOfRestartAttempts, - functionClusterAffiliation__, - coremask__, - uid, - gid, - path__, - securityPolicyDetails__, - executable_reportingBehavior, - startupConfig__, - sgids__); -} - -struct ProcessStartupConfig FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessStartupConfigBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_IDENTIFIER = 4, - VT_ENTERTIMEOUTVALUE = 6, - VT_EXITTIMEOUTVALUE = 8, - VT_SCHEDULINGPRIORITY = 10, - VT_SCHEDULINGPOLICY = 12, - VT_EXECUTIONERROR = 14, - VT_TERMINATIONBEHAVIOR = 16, - VT_EXECUTIONDEPENDENCY = 18, - VT_PROCESSGROUPSTATEDEPENDENCY = 20, - VT_ENVIRONMENTVARIABLE = 22, - VT_PROCESSARGUMENT = 24, - VT_MEMORYUSAGE = 26 - }; - const ::flatbuffers::String *identifier() const { - return GetPointer(VT_IDENTIFIER); - } - uint32_t enterTimeoutValue() const { - return GetField(VT_ENTERTIMEOUTVALUE, 0); - } - uint32_t exitTimeoutValue() const { - return GetField(VT_EXITTIMEOUTVALUE, 0); - } - const ::flatbuffers::String *schedulingPriority() const { - return GetPointer(VT_SCHEDULINGPRIORITY); - } - const ::flatbuffers::String *schedulingPolicy() const { - return GetPointer(VT_SCHEDULINGPOLICY); - } - const ::flatbuffers::String *executionError() const { - return GetPointer(VT_EXECUTIONERROR); - } - LMFlatBuffer::TerminationBehaviorEnum terminationBehavior() const { - return static_cast(GetField(VT_TERMINATIONBEHAVIOR, 0)); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *executionDependency() const { - return GetPointer> *>(VT_EXECUTIONDEPENDENCY); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *processGroupStateDependency() const { - return GetPointer> *>(VT_PROCESSGROUPSTATEDEPENDENCY); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *environmentVariable() const { - return GetPointer> *>(VT_ENVIRONMENTVARIABLE); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *processArgument() const { - return GetPointer> *>(VT_PROCESSARGUMENT); - } - uint64_t memoryUsage() const { - return GetField(VT_MEMORYUSAGE, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_IDENTIFIER) && - verifier.VerifyString(identifier()) && - VerifyField(verifier, VT_ENTERTIMEOUTVALUE, 4) && - VerifyField(verifier, VT_EXITTIMEOUTVALUE, 4) && - VerifyOffset(verifier, VT_SCHEDULINGPRIORITY) && - verifier.VerifyString(schedulingPriority()) && - VerifyOffset(verifier, VT_SCHEDULINGPOLICY) && - verifier.VerifyString(schedulingPolicy()) && - VerifyOffset(verifier, VT_EXECUTIONERROR) && - verifier.VerifyString(executionError()) && - VerifyField(verifier, VT_TERMINATIONBEHAVIOR, 1) && - VerifyOffset(verifier, VT_EXECUTIONDEPENDENCY) && - verifier.VerifyVector(executionDependency()) && - verifier.VerifyVectorOfTables(executionDependency()) && - VerifyOffset(verifier, VT_PROCESSGROUPSTATEDEPENDENCY) && - verifier.VerifyVector(processGroupStateDependency()) && - verifier.VerifyVectorOfTables(processGroupStateDependency()) && - VerifyOffset(verifier, VT_ENVIRONMENTVARIABLE) && - verifier.VerifyVector(environmentVariable()) && - verifier.VerifyVectorOfTables(environmentVariable()) && - VerifyOffset(verifier, VT_PROCESSARGUMENT) && - verifier.VerifyVector(processArgument()) && - verifier.VerifyVectorOfTables(processArgument()) && - VerifyField(verifier, VT_MEMORYUSAGE, 8) && - verifier.EndTable(); - } -}; - -struct ProcessStartupConfigBuilder { - typedef ProcessStartupConfig Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_identifier(::flatbuffers::Offset<::flatbuffers::String> identifier) { - fbb_.AddOffset(ProcessStartupConfig::VT_IDENTIFIER, identifier); - } - void add_enterTimeoutValue(uint32_t enterTimeoutValue) { - fbb_.AddElement(ProcessStartupConfig::VT_ENTERTIMEOUTVALUE, enterTimeoutValue, 0); - } - void add_exitTimeoutValue(uint32_t exitTimeoutValue) { - fbb_.AddElement(ProcessStartupConfig::VT_EXITTIMEOUTVALUE, exitTimeoutValue, 0); - } - void add_schedulingPriority(::flatbuffers::Offset<::flatbuffers::String> schedulingPriority) { - fbb_.AddOffset(ProcessStartupConfig::VT_SCHEDULINGPRIORITY, schedulingPriority); - } - void add_schedulingPolicy(::flatbuffers::Offset<::flatbuffers::String> schedulingPolicy) { - fbb_.AddOffset(ProcessStartupConfig::VT_SCHEDULINGPOLICY, schedulingPolicy); - } - void add_executionError(::flatbuffers::Offset<::flatbuffers::String> executionError) { - fbb_.AddOffset(ProcessStartupConfig::VT_EXECUTIONERROR, executionError); - } - void add_terminationBehavior(LMFlatBuffer::TerminationBehaviorEnum terminationBehavior) { - fbb_.AddElement(ProcessStartupConfig::VT_TERMINATIONBEHAVIOR, static_cast(terminationBehavior), 0); - } - void add_executionDependency(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> executionDependency) { - fbb_.AddOffset(ProcessStartupConfig::VT_EXECUTIONDEPENDENCY, executionDependency); - } - void add_processGroupStateDependency(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> processGroupStateDependency) { - fbb_.AddOffset(ProcessStartupConfig::VT_PROCESSGROUPSTATEDEPENDENCY, processGroupStateDependency); - } - void add_environmentVariable(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> environmentVariable) { - fbb_.AddOffset(ProcessStartupConfig::VT_ENVIRONMENTVARIABLE, environmentVariable); - } - void add_processArgument(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> processArgument) { - fbb_.AddOffset(ProcessStartupConfig::VT_PROCESSARGUMENT, processArgument); - } - void add_memoryUsage(uint64_t memoryUsage) { - fbb_.AddElement(ProcessStartupConfig::VT_MEMORYUSAGE, memoryUsage, 0); - } - explicit ProcessStartupConfigBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcessStartupConfig( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> identifier = 0, - uint32_t enterTimeoutValue = 0, - uint32_t exitTimeoutValue = 0, - ::flatbuffers::Offset<::flatbuffers::String> schedulingPriority = 0, - ::flatbuffers::Offset<::flatbuffers::String> schedulingPolicy = 0, - ::flatbuffers::Offset<::flatbuffers::String> executionError = 0, - LMFlatBuffer::TerminationBehaviorEnum terminationBehavior = LMFlatBuffer::TerminationBehaviorEnum_ProcessIsNotSelfTerminating, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> executionDependency = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> processGroupStateDependency = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> environmentVariable = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> processArgument = 0, - uint64_t memoryUsage = 0) { - ProcessStartupConfigBuilder builder_(_fbb); - builder_.add_memoryUsage(memoryUsage); - builder_.add_processArgument(processArgument); - builder_.add_environmentVariable(environmentVariable); - builder_.add_processGroupStateDependency(processGroupStateDependency); - builder_.add_executionDependency(executionDependency); - builder_.add_executionError(executionError); - builder_.add_schedulingPolicy(schedulingPolicy); - builder_.add_schedulingPriority(schedulingPriority); - builder_.add_exitTimeoutValue(exitTimeoutValue); - builder_.add_enterTimeoutValue(enterTimeoutValue); - builder_.add_identifier(identifier); - builder_.add_terminationBehavior(terminationBehavior); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessStartupConfigDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *identifier = nullptr, - uint32_t enterTimeoutValue = 0, - uint32_t exitTimeoutValue = 0, - const char *schedulingPriority = nullptr, - const char *schedulingPolicy = nullptr, - const char *executionError = nullptr, - LMFlatBuffer::TerminationBehaviorEnum terminationBehavior = LMFlatBuffer::TerminationBehaviorEnum_ProcessIsNotSelfTerminating, - const std::vector<::flatbuffers::Offset> *executionDependency = nullptr, - const std::vector<::flatbuffers::Offset> *processGroupStateDependency = nullptr, - const std::vector<::flatbuffers::Offset> *environmentVariable = nullptr, - const std::vector<::flatbuffers::Offset> *processArgument = nullptr, - uint64_t memoryUsage = 0) { - auto identifier__ = identifier ? _fbb.CreateString(identifier) : 0; - auto schedulingPriority__ = schedulingPriority ? _fbb.CreateString(schedulingPriority) : 0; - auto schedulingPolicy__ = schedulingPolicy ? _fbb.CreateString(schedulingPolicy) : 0; - auto executionError__ = executionError ? _fbb.CreateString(executionError) : 0; - auto executionDependency__ = executionDependency ? _fbb.CreateVector<::flatbuffers::Offset>(*executionDependency) : 0; - auto processGroupStateDependency__ = processGroupStateDependency ? _fbb.CreateVector<::flatbuffers::Offset>(*processGroupStateDependency) : 0; - auto environmentVariable__ = environmentVariable ? _fbb.CreateVector<::flatbuffers::Offset>(*environmentVariable) : 0; - auto processArgument__ = processArgument ? _fbb.CreateVector<::flatbuffers::Offset>(*processArgument) : 0; - return LMFlatBuffer::CreateProcessStartupConfig( - _fbb, - identifier__, - enterTimeoutValue, - exitTimeoutValue, - schedulingPriority__, - schedulingPolicy__, - executionError__, - terminationBehavior, - executionDependency__, - processGroupStateDependency__, - environmentVariable__, - processArgument__, - memoryUsage); -} - -struct ProcessGroupStateDependency FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessGroupStateDependencyBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_STATEMACHINE_NAME = 4, - VT_STATENAME = 6 - }; - const ::flatbuffers::String *stateMachine_name() const { - return GetPointer(VT_STATEMACHINE_NAME); - } - const ::flatbuffers::String *stateName() const { - return GetPointer(VT_STATENAME); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_STATEMACHINE_NAME) && - verifier.VerifyString(stateMachine_name()) && - VerifyOffset(verifier, VT_STATENAME) && - verifier.VerifyString(stateName()) && - verifier.EndTable(); - } -}; - -struct ProcessGroupStateDependencyBuilder { - typedef ProcessGroupStateDependency Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_stateMachine_name(::flatbuffers::Offset<::flatbuffers::String> stateMachine_name) { - fbb_.AddOffset(ProcessGroupStateDependency::VT_STATEMACHINE_NAME, stateMachine_name); - } - void add_stateName(::flatbuffers::Offset<::flatbuffers::String> stateName) { - fbb_.AddOffset(ProcessGroupStateDependency::VT_STATENAME, stateName); - } - explicit ProcessGroupStateDependencyBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcessGroupStateDependency( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> stateMachine_name = 0, - ::flatbuffers::Offset<::flatbuffers::String> stateName = 0) { - ProcessGroupStateDependencyBuilder builder_(_fbb); - builder_.add_stateName(stateName); - builder_.add_stateMachine_name(stateMachine_name); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessGroupStateDependencyDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *stateMachine_name = nullptr, - const char *stateName = nullptr) { - auto stateMachine_name__ = stateMachine_name ? _fbb.CreateString(stateMachine_name) : 0; - auto stateName__ = stateName ? _fbb.CreateString(stateName) : 0; - return LMFlatBuffer::CreateProcessGroupStateDependency( - _fbb, - stateMachine_name__, - stateName__); -} - -struct ProcessExecutionDependency FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessExecutionDependencyBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_STATENAME = 4, - VT_TARGETPROCESS_IDENTIFIER = 6 - }; - const ::flatbuffers::String *stateName() const { - return GetPointer(VT_STATENAME); - } - const ::flatbuffers::String *targetProcess_identifier() const { - return GetPointer(VT_TARGETPROCESS_IDENTIFIER); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_STATENAME) && - verifier.VerifyString(stateName()) && - VerifyOffset(verifier, VT_TARGETPROCESS_IDENTIFIER) && - verifier.VerifyString(targetProcess_identifier()) && - verifier.EndTable(); - } -}; - -struct ProcessExecutionDependencyBuilder { - typedef ProcessExecutionDependency Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_stateName(::flatbuffers::Offset<::flatbuffers::String> stateName) { - fbb_.AddOffset(ProcessExecutionDependency::VT_STATENAME, stateName); - } - void add_targetProcess_identifier(::flatbuffers::Offset<::flatbuffers::String> targetProcess_identifier) { - fbb_.AddOffset(ProcessExecutionDependency::VT_TARGETPROCESS_IDENTIFIER, targetProcess_identifier); - } - explicit ProcessExecutionDependencyBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcessExecutionDependency( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> stateName = 0, - ::flatbuffers::Offset<::flatbuffers::String> targetProcess_identifier = 0) { - ProcessExecutionDependencyBuilder builder_(_fbb); - builder_.add_targetProcess_identifier(targetProcess_identifier); - builder_.add_stateName(stateName); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessExecutionDependencyDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *stateName = nullptr, - const char *targetProcess_identifier = nullptr) { - auto stateName__ = stateName ? _fbb.CreateString(stateName) : 0; - auto targetProcess_identifier__ = targetProcess_identifier ? _fbb.CreateString(targetProcess_identifier) : 0; - return LMFlatBuffer::CreateProcessExecutionDependency( - _fbb, - stateName__, - targetProcess_identifier__); -} - -struct EnvironmentVariable FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef EnvironmentVariableBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_KEY = 4, - VT_VALUE = 6 - }; - const ::flatbuffers::String *key() const { - return GetPointer(VT_KEY); - } - const ::flatbuffers::String *value() const { - return GetPointer(VT_VALUE); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_KEY) && - verifier.VerifyString(key()) && - VerifyOffset(verifier, VT_VALUE) && - verifier.VerifyString(value()) && - verifier.EndTable(); - } -}; - -struct EnvironmentVariableBuilder { - typedef EnvironmentVariable Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_key(::flatbuffers::Offset<::flatbuffers::String> key) { - fbb_.AddOffset(EnvironmentVariable::VT_KEY, key); - } - void add_value(::flatbuffers::Offset<::flatbuffers::String> value) { - fbb_.AddOffset(EnvironmentVariable::VT_VALUE, value); - } - explicit EnvironmentVariableBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateEnvironmentVariable( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> key = 0, - ::flatbuffers::Offset<::flatbuffers::String> value = 0) { - EnvironmentVariableBuilder builder_(_fbb); - builder_.add_value(value); - builder_.add_key(key); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateEnvironmentVariableDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *key = nullptr, - const char *value = nullptr) { - auto key__ = key ? _fbb.CreateString(key) : 0; - auto value__ = value ? _fbb.CreateString(value) : 0; - return LMFlatBuffer::CreateEnvironmentVariable( - _fbb, - key__, - value__); -} - -struct ProcessArgument FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessArgumentBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_ARGUMENT = 4 - }; - const ::flatbuffers::String *argument() const { - return GetPointer(VT_ARGUMENT); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_ARGUMENT) && - verifier.VerifyString(argument()) && - verifier.EndTable(); - } -}; - -struct ProcessArgumentBuilder { - typedef ProcessArgument Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_argument(::flatbuffers::Offset<::flatbuffers::String> argument) { - fbb_.AddOffset(ProcessArgument::VT_ARGUMENT, argument); - } - explicit ProcessArgumentBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcessArgument( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> argument = 0) { - ProcessArgumentBuilder builder_(_fbb); - builder_.add_argument(argument); - return builder_.Finish(); -} - -inline ::flatbuffers::Offset CreateProcessArgumentDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *argument = nullptr) { - auto argument__ = argument ? _fbb.CreateString(argument) : 0; - return LMFlatBuffer::CreateProcessArgument( - _fbb, - argument__); -} - -struct ProcessSgid FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ProcessSgidBuilder Builder; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SGID = 4 - }; - uint32_t sgid() const { - return GetField(VT_SGID, 0); - } - template - bool Verify(::flatbuffers::VerifierTemplate &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SGID, 4) && - verifier.EndTable(); - } -}; - -struct ProcessSgidBuilder { - typedef ProcessSgid Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_sgid(uint32_t sgid) { - fbb_.AddElement(ProcessSgid::VT_SGID, sgid, 0); - } - explicit ProcessSgidBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProcessSgid( - ::flatbuffers::FlatBufferBuilder &_fbb, - uint32_t sgid = 0) { - ProcessSgidBuilder builder_(_fbb); - builder_.add_sgid(sgid); - return builder_.Finish(); -} - -inline const LMFlatBuffer::LMEcuCfg *GetLMEcuCfg(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const LMFlatBuffer::LMEcuCfg *GetSizePrefixedLMEcuCfg(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline const char *LMEcuCfgIdentifier() { - return "BLMR"; -} - -inline bool LMEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, LMEcuCfgIdentifier()); -} - -inline bool SizePrefixedLMEcuCfgBufferHasIdentifier(const void *buf) { - return ::flatbuffers::BufferHasIdentifier( - buf, LMEcuCfgIdentifier(), true); -} - -template -inline bool VerifyLMEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifyBuffer(LMEcuCfgIdentifier()); -} - -template -inline bool VerifySizePrefixedLMEcuCfgBuffer( - ::flatbuffers::VerifierTemplate &verifier) { - return verifier.template VerifySizePrefixedBuffer(LMEcuCfgIdentifier()); -} - -inline const char *LMEcuCfgExtension() { - return "bin"; -} - -inline void FinishLMEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root, LMEcuCfgIdentifier()); -} - -inline void FinishSizePrefixedLMEcuCfgBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root, LMEcuCfgIdentifier()); -} - -} // namespace LMFlatBuffer - -#endif // FLATBUFFERS_GENERATED_LMFLATCFG_LMFLATBUFFER_H_ diff --git a/score/launch_manager/daemon/src/main.cpp b/score/launch_manager/daemon/src/main.cpp index 25babbb88..a24dc13f1 100644 --- a/score/launch_manager/daemon/src/main.cpp +++ b/score/launch_manager/daemon/src/main.cpp @@ -23,29 +23,11 @@ #include "score/mw/launch_manager/recovery_client/recovery_client.hpp" #include "score/mw/launch_manager/alive_monitor/details/daemon/AliveMonitorImpl.hpp" #include "score/mw/launch_manager/alive_monitor/details/watchdog/WatchdogImpl.hpp" +#include "score/mw/launch_manager/configuration/flatbuffer_config_loader.hpp" using namespace std; using namespace score::lcm::internal; -/// @brief Initializes the LCM daemon. -/// This function initializes the LCM daemon by calling the initialize() method -/// of the provided ProcessGroupManager object. It logs an information message -/// if initialization is successful and a fatal error message if it fails. -/// @param process_group_manager The ProcessGroupManager object to initialize. -/// @return True if initialization succeeds, false otherwise. -bool initializeLCMDaemon(ProcessGroupManager& process_group_manager) -{ - if (process_group_manager.initialize()) - { - LM_LOG_INFO() << "LCM started successfully"; - return true; - } - else - { - LM_LOG_FATAL() << "LCM startup failed"; - return false; - } -} /// @brief Runs the LCM daemon. /// This function runs the LCM daemon by calling the run() method of the provided @@ -104,8 +86,15 @@ void reserveFD(int fd) /// @param argv Array of command-line arguments. /// @return The exit code. 0 for success, non-zero for failure. // coverity[autosar_cpp14_a15_3_3_violation:FALSE] Only logging occurs outside the try-catch enclosing main(). -int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) +int main(int argc, const char* argv[]) { + const char* config_path = "etc/launch_manager_config.bin"; + int opt; + while ((opt = getopt(argc, const_cast(argv), "c:")) != -1) { + if (opt == 'c') { + config_path = optarg; + } + } // reserve files descriptor osal::IpcCommsSync::sync_fd (fd3) and // osal::IpcCommsSync::control_client_handler_nudge_fd (fd4) for communication tpyes: kNoComms !fd3 & !fd4 // kReporting fd3 & !fd4 @@ -127,26 +116,40 @@ int main([[maybe_unused]] int argc, [[maybe_unused]] const char* argv[]) // } LM_LOG_DEBUG() << "Launch Manager Started !!!!"; + + score::mw::launch_manager::configuration::FlatbufferConfigLoader config_loader; + auto config_result = config_loader.load(config_path); + if (!config_result.has_value()) { + LM_LOG_FATAL() << "Failed to load config from: " << config_path; + return EXIT_FAILURE; + } + std::shared_ptr recoveryClient{std::make_shared()}; std::unique_ptr watchdog{ std::make_unique()}; auto process_state_notifier = std::make_unique(); std::unique_ptr healthMonitor{ std::make_unique( - recoveryClient, std::move(watchdog), process_state_notifier->constructReceiver())}; + recoveryClient, std::move(watchdog), process_state_notifier->constructReceiver(), + *config_result)}; // passes by const ref; config_result stays alive std::unique_ptr aliveMonitorThread{ std::make_unique(std::move(healthMonitor))}; std::unique_ptr process_group_manager = std::make_unique( std::move(aliveMonitorThread), recoveryClient, std::move(process_state_notifier)); - if (initializeLCMDaemon(*process_group_manager)) + if (process_group_manager->initialize(*config_result)) { + LM_LOG_INFO() << "LCM started successfully"; if (runLCMDaemon(*process_group_manager)) { exit_code = EXIT_SUCCESS; } } + else + { + LM_LOG_FATAL() << "LCM startup failed"; + } if (process_group_manager) { diff --git a/score/launch_manager/daemon/src/process_group_manager/BUILD b/score/launch_manager/daemon/src/process_group_manager/BUILD index c1986eeaf..d187ccd76 100644 --- a/score/launch_manager/daemon/src/process_group_manager/BUILD +++ b/score/launch_manager/daemon/src/process_group_manager/BUILD @@ -59,6 +59,7 @@ cc_library( "//score/launch_manager/daemon/src/common:identifier_hash", "//score/launch_manager/daemon/src/common/concurrency:mpmc_concurrent_queue", "//score/launch_manager/daemon/src/common/concurrency:workerthread", + "//score/launch_manager/daemon/src/configuration:config", "//score/launch_manager/daemon/src/configuration:configuration_adapter", "//score/launch_manager/daemon/src/control:control_client_channel", "//score/launch_manager/daemon/src/osal:ipc_comms", diff --git a/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp b/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp index 41142a966..40b614504 100644 --- a/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp +++ b/score/launch_manager/daemon/src/process_group_manager/details/process_group_manager.cpp @@ -69,7 +69,7 @@ void ProcessGroupManager::setLaunchManagerConfiguration(const OsProcess* launch_ } } -bool ProcessGroupManager::initialize() +bool ProcessGroupManager::initialize(const score::mw::launch_manager::configuration::Config& config) { // setup signal handler em_cancelled.store(false); @@ -90,7 +90,7 @@ bool ProcessGroupManager::initialize() sigaction(SIGUSR2, &action, NULL); sigaction(SIGVTALRM, &action, NULL); - if (!initializeControlClientHandler() || !initializeProcessGroups()) + if (!initializeControlClientHandler() || !initializeProcessGroups(config)) { return false; } @@ -172,11 +172,11 @@ inline bool ProcessGroupManager::initializeControlClientHandler() return result; } -inline bool ProcessGroupManager::initializeProcessGroups() +inline bool ProcessGroupManager::initializeProcessGroups(const score::mw::launch_manager::configuration::Config& config) { bool success = false; - if (configuration_adapter_.initialize()) + if (configuration_adapter_.initialize(config)) { auto pg_list = configuration_adapter_.getListOfProcessGroups().value_or(nullptr); diff --git a/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp b/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp index b5acf365d..54ed219e9 100644 --- a/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp +++ b/score/launch_manager/daemon/src/process_group_manager/process_group_manager.hpp @@ -20,6 +20,7 @@ #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/control/control_client_channel.hpp" +#include "score/mw/launch_manager/configuration/config.hpp" #include "score/mw/launch_manager/configuration/configuration_adapter.hpp" #include "score/mw/launch_manager/process_group_manager/iprocess.hpp" #include "score/mw/launch_manager/process_group_manager/details/graph.hpp" @@ -69,14 +70,14 @@ class ProcessGroupManager final std::unique_ptr process_state_notifier); /// @brief Initializes the process group manager. - /// Loads the flat configuration through ConfigurationAdapter. /// Sets up a signal handler for SIGINT and SIGTERM so that the main loop of - /// the run() method will be exited in the event of those signals + /// the run() method will be exited in the event of those signals. /// Creates the process map, worker threads and worker job queues. /// Creates and initialises the shared memory for the nudge semaphore, always using FD #4, /// and stores a pointer to it. + /// @param config The fully-loaded configuration to build process groups from. /// @return Returns true if initialization was successful, false otherwise. - bool initialize(); + bool initialize(const score::mw::launch_manager::configuration::Config& config); /// @brief De-initialises the process group manager /// deletes worker threads, worker jobs and the process map and then de-initialises the configuration manager @@ -260,7 +261,7 @@ class ProcessGroupManager final /// @brief Initializes the process groups. /// @return Returns true if initialization was successful, false otherwise. - inline bool initializeProcessGroups(); + inline bool initializeProcessGroups(const score::mw::launch_manager::configuration::Config& config); /// @brief Creates process component objects, including the job queue and worker threads. inline void createProcessComponentsObjects(); diff --git a/tests/integration/complex_monitoring/complex_monitoring.py b/tests/integration/complex_monitoring/complex_monitoring.py index ec47e5952..641f8b1d6 100644 --- a/tests/integration/complex_monitoring/complex_monitoring.py +++ b/tests/integration/complex_monitoring/complex_monitoring.py @@ -35,6 +35,7 @@ def test_complex_monitoring(target, setup_test, assert_test_results, remote_test run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=4.0, diff --git a/tests/integration/crash_on_startup/crash_on_startup.py b/tests/integration/crash_on_startup/crash_on_startup.py index b88bc439f..d4e6a8cb1 100644 --- a/tests/integration/crash_on_startup/crash_on_startup.py +++ b/tests/integration/crash_on_startup/crash_on_startup.py @@ -35,6 +35,7 @@ def test_crash_on_startup(target, setup_test, assert_test_results, remote_test_d run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=6.0, diff --git a/tests/integration/incorrect_config_non_reporting/BUILD b/tests/integration/incorrect_config_non_reporting/BUILD index 883d631ac..54093c671 100644 --- a/tests/integration/incorrect_config_non_reporting/BUILD +++ b/tests/integration/incorrect_config_non_reporting/BUILD @@ -13,11 +13,7 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_files") load("@rules_pkg//pkg:tar.bzl", "pkg_tar") -load("@score_itf//:defs.bzl", "py_itf_test") -load("@score_lifecycle_pip//:requirements.bzl", "all_requirements") -load("@score_tooling//:defs.bzl", "score_py_pytest") load("//:defs.bzl", "launch_manager_config") -load("//config:flatbuffers_rules.bzl", "flatbuffer_json_to_bin") load("//tests/utils/bazel:integration.bzl", "integration_test") launch_manager_config( diff --git a/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py b/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py index 2625326e9..ba8278f9d 100644 --- a/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py +++ b/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py @@ -33,6 +33,7 @@ def test_incorrect_config_non_reporting( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, diff --git a/tests/integration/process_crash_monitoring/process_crash_monitoring.py b/tests/integration/process_crash_monitoring/process_crash_monitoring.py index 061982f79..654d687c6 100644 --- a/tests/integration/process_crash_monitoring/process_crash_monitoring.py +++ b/tests/integration/process_crash_monitoring/process_crash_monitoring.py @@ -34,6 +34,7 @@ def test_process_crash_monitoring( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=10.0, diff --git a/tests/integration/process_launch_args/process_launch_args.py b/tests/integration/process_launch_args/process_launch_args.py index 524afa1d8..8227458bb 100644 --- a/tests/integration/process_launch_args/process_launch_args.py +++ b/tests/integration/process_launch_args/process_launch_args.py @@ -37,6 +37,7 @@ def test_process_launch_args(target, setup_test, assert_test_results, remote_tes run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, diff --git a/tests/integration/smoke/BUILD b/tests/integration/smoke/BUILD index e1fdd7f02..ed39142c2 100644 --- a/tests/integration/smoke/BUILD +++ b/tests/integration/smoke/BUILD @@ -13,18 +13,9 @@ load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_files") load("@rules_pkg//pkg:tar.bzl", "pkg_tar") -load("@score_itf//:defs.bzl", "py_itf_test") -load("@score_lifecycle_pip//:requirements.bzl", "all_requirements") -load("@score_tooling//:defs.bzl", "score_py_pytest") load("//:defs.bzl", "launch_manager_config") -load("//config:flatbuffers_rules.bzl", "flatbuffer_json_to_bin") load("//tests/utils/bazel:integration.bzl", "integration_test") -exports_files( - ["lm_demo.json"], - visibility = ["//examples:__subpackages__"], -) - launch_manager_config( name = "lm_smoketest_config", config = "//tests/integration/smoke:lifecycle_smoketest.json", diff --git a/tests/integration/smoke/smoke.py b/tests/integration/smoke/smoke.py index 125a86ca9..92bb0b01c 100644 --- a/tests/integration/smoke/smoke.py +++ b/tests/integration/smoke/smoke.py @@ -32,6 +32,7 @@ def test_smoke(target, setup_test, assert_test_results, remote_test_dir): run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=3.0, diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index 46aff1d05..f658f4ec3 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -37,6 +37,7 @@ def test_switch_run_target(target, setup_test, assert_test_results, remote_test_ run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), + args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, From c2e120cf883e1de78e5e69fbc78342b0fa5a8e65 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Thu, 18 Jun 2026 13:15:49 +0200 Subject: [PATCH 3/7] Add tests --- .../daemon/src/configuration/BUILD | 10 + .../details/configuration_adapter_UT.cpp | 340 ++++++++++++++++++ scripts/config_mapping/unit_tests.py | 242 ++++++++++++- 3 files changed, 591 insertions(+), 1 deletion(-) create mode 100644 score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp diff --git a/score/launch_manager/daemon/src/configuration/BUILD b/score/launch_manager/daemon/src/configuration/BUILD index e7ead9d0d..1555bb630 100644 --- a/score/launch_manager/daemon/src/configuration/BUILD +++ b/score/launch_manager/daemon/src/configuration/BUILD @@ -133,3 +133,13 @@ cc_library( "//score/launch_manager/daemon/src/process_state_client:posix_process", ], ) + +cc_test( + name = "configuration_adapter_UT", + srcs = ["details/configuration_adapter_UT.cpp"], + visibility = ["//tests:__subpackages__"], + deps = [ + ":configuration_adapter", + "@googletest//:gtest_main", + ], +) diff --git a/score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp b/score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp new file mode 100644 index 000000000..b1e915792 --- /dev/null +++ b/score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp @@ -0,0 +1,340 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ +#include "score/mw/launch_manager/configuration/configuration_adapter.hpp" +#include "score/mw/launch_manager/configuration/config.hpp" + +#include +#include + +#include +#include + +namespace score::mw::launch_manager::configuration { +namespace { + +using ::testing::Eq; +using ::testing::IsNull; +using ::testing::Ne; +using ::testing::NotNull; + +using IdentifierHash = score::lcm::IdentifierHash; + +Config makeMinimalConfig() +{ + ComponentConfig comp_a; + comp_a.name = "comp_a"; + comp_a.description = "Component A"; + comp_a.component_properties.binary_name = "comp_a_bin"; + comp_a.component_properties.application_profile.application_type = ApplicationType::ReportingAndSupervised; + comp_a.component_properties.application_profile.is_self_terminating = false; + comp_a.component_properties.application_profile.alive_supervision = ComponentAliveSupervision{500, 2, 1, 3}; + comp_a.component_properties.ready_condition = ReadyCondition{ProcessState::Running}; + comp_a.deployment_config.ready_timeout_ms = 500; + comp_a.deployment_config.shutdown_timeout_ms = 500; + comp_a.deployment_config.bin_dir = "/opt/apps"; + comp_a.deployment_config.working_dir = "/tmp"; + comp_a.deployment_config.sandbox.uid = 1000; + comp_a.deployment_config.sandbox.gid = 1000; + comp_a.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_a.deployment_config.sandbox.scheduling_priority = 0; + + ComponentConfig comp_b; + comp_b.name = "comp_b"; + comp_b.description = "Component B"; + comp_b.component_properties.binary_name = "comp_b_bin"; + comp_b.component_properties.application_profile.application_type = ApplicationType::Native; + comp_b.component_properties.application_profile.is_self_terminating = true; + comp_b.component_properties.depends_on = {"comp_a"}; + comp_b.component_properties.ready_condition = ReadyCondition{ProcessState::Running}; + comp_b.deployment_config.ready_timeout_ms = 1000; + comp_b.deployment_config.shutdown_timeout_ms = 1000; + comp_b.deployment_config.bin_dir = "/opt/apps"; + comp_b.deployment_config.working_dir = "/tmp"; + comp_b.deployment_config.sandbox.uid = 1000; + comp_b.deployment_config.sandbox.gid = 1000; + comp_b.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_b.deployment_config.sandbox.scheduling_priority = 0; + + std::vector components; + components.push_back(std::move(comp_a)); + components.push_back(std::move(comp_b)); + + RunTargetConfig startup; + startup.name = "Startup"; + startup.description = "Initial run target"; + startup.depends_on = {"comp_a"}; + startup.transition_timeout_ms = 5000; + startup.recovery_action.run_target = "fallback_run_target"; + + RunTargetConfig full; + full.name = "Full"; + full.description = "Full run target"; + full.depends_on = {"comp_b", "Startup"}; + full.transition_timeout_ms = 5000; + full.recovery_action.run_target = "fallback_run_target"; + + std::vector run_targets; + run_targets.push_back(std::move(startup)); + run_targets.push_back(std::move(full)); + + FallbackRunTargetConfig fallback; + fallback.description = "Safe state"; + fallback.transition_timeout_ms = 1500; + + AliveSupervisionConfig alive; + alive.evaluation_cycle_ms = 500; + + return ConfigBuilder{} + .setComponents(std::move(components)) + .setRunTargets(std::move(run_targets)) + .setInitialRunTarget("Startup") + .setFallbackRunTarget(std::move(fallback)) + .setAliveSupervision(alive) + .build(); +} + +class ConfigurationAdapterTest : public ::testing::Test { + protected: + void SetUp() override + { + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "explorative-testing"); + + config_ = makeMinimalConfig(); + adapter_.initialize(config_); + } + + void TearDown() override + { + adapter_.deinitialize(); + } + + Config config_{makeMinimalConfig()}; + ConfigurationAdapter adapter_; +}; + +TEST_F(ConfigurationAdapterTest, GetListOfProcessGroupsReturnsSingleImplicitGroup) +{ + RecordProperty("Description", "After initialize, getListOfProcessGroups returns a list with the single MainPG group."); + + auto result = adapter_.getListOfProcessGroups(); + + ASSERT_TRUE(result.has_value()); + const auto& groups = **result; + ASSERT_THAT(groups.size(), Eq(1U)); + EXPECT_THAT(groups[0], Eq(IdentifierHash{"MainPG"})); +} + +TEST_F(ConfigurationAdapterTest, GetMainPGStartupStateMapsToInitialRunTarget) +{ + RecordProperty("Description", "getMainPGStartupState returns MainPG/Startup matching Config::initialRunTarget."); + + auto result = adapter_.getMainPGStartupState(); + + ASSERT_TRUE(result.has_value()); + const auto* state_id = *result; + EXPECT_THAT(state_id->pg_name_, Eq(IdentifierHash{"MainPG"})); + EXPECT_THAT(state_id->pg_state_name_, Eq(IdentifierHash{"MainPG/Startup"})); +} + +TEST_F(ConfigurationAdapterTest, GetNameOfOffStateMapsToMainPGOff) +{ + RecordProperty("Description", "getNameOfOffState returns MainPG/Off for the implicit process group."); + + auto off_state = adapter_.getNameOfOffState(IdentifierHash{"MainPG"}); + + EXPECT_THAT(off_state, Eq(IdentifierHash{"MainPG/Off"})); +} + +TEST_F(ConfigurationAdapterTest, GetNameOfRecoveryStateMapsToFallbackRunTarget) +{ + RecordProperty("Description", "getNameOfRecoveryState returns MainPG/fallback_run_target."); + + auto recovery = adapter_.getNameOfRecoveryState(IdentifierHash{"MainPG"}); + + EXPECT_THAT(recovery, Eq(IdentifierHash{"MainPG/fallback_run_target"})); +} + +TEST_F(ConfigurationAdapterTest, GetProcessIndexesListResolvesRunTargetDependencies) +{ + RecordProperty("Description", "getProcessIndexesList resolves RunTarget depends_on to component indexes."); + + score::lcm::internal::ProcessGroupStateID startup_id{ + IdentifierHash{"MainPG"}, IdentifierHash{"MainPG/Startup"}}; + + auto result = adapter_.getProcessIndexesList(startup_id); + + ASSERT_TRUE(result.has_value()); + const auto& indexes = **result; + EXPECT_THAT(indexes.size(), Eq(1U)); + EXPECT_THAT(indexes[0], Eq(0U)); +} + +TEST_F(ConfigurationAdapterTest, GetProcessIndexesListResolvesTransitiveDependencies) +{ + RecordProperty("Description", "Full run target depends on comp_b and Startup; transitive resolution yields both component indexes."); + + score::lcm::internal::ProcessGroupStateID full_id{ + IdentifierHash{"MainPG"}, IdentifierHash{"MainPG/Full"}}; + + auto result = adapter_.getProcessIndexesList(full_id); + + ASSERT_TRUE(result.has_value()); + const auto& indexes = **result; + EXPECT_THAT(indexes.size(), Eq(2U)); + + bool has_comp_a = std::find(indexes.begin(), indexes.end(), 0U) != indexes.end(); + bool has_comp_b = std::find(indexes.begin(), indexes.end(), 1U) != indexes.end(); + EXPECT_TRUE(has_comp_a); + EXPECT_TRUE(has_comp_b); +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessConfigurationMapsComponentFields) +{ + RecordProperty("Description", "getOsProcessConfiguration maps ComponentConfig fields to legacy OsProcess struct."); + + IdentifierHash pg_name{"MainPG"}; + + auto result = adapter_.getOsProcessConfiguration(pg_name, 0U); + + ASSERT_TRUE(result.has_value()); + const auto* os_proc = *result; + + EXPECT_THAT(os_proc->process_id_, Eq(IdentifierHash{"comp_a"})); + EXPECT_THAT(os_proc->process_number_, Eq(0U)); + EXPECT_THAT(os_proc->startup_config_.executable_path_, Eq("/opt/apps/comp_a_bin")); + EXPECT_THAT(os_proc->startup_config_.short_name_, Eq("comp_a")); + EXPECT_THAT(os_proc->startup_config_.uid_, Eq(1000U)); + EXPECT_THAT(os_proc->startup_config_.gid_, Eq(1000U)); + EXPECT_THAT(os_proc->pgm_config_.is_self_terminating_, Eq(false)); + EXPECT_THAT(os_proc->pgm_config_.startup_timeout_ms_, Eq(std::chrono::milliseconds{500})); + EXPECT_THAT(os_proc->pgm_config_.termination_timeout_ms_, Eq(std::chrono::milliseconds{500})); +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessConfigurationInjectsAliveInterfaceForSupervised) +{ + RecordProperty("Description", "Supervised components get LCM_ALIVE_INTERFACE_PATH injected into envp."); + + IdentifierHash pg_name{"MainPG"}; + auto result = adapter_.getOsProcessConfiguration(pg_name, 0U); + ASSERT_TRUE(result.has_value()); + const auto* os_proc = *result; + + bool found = false; + for (size_t i = 0; os_proc->startup_config_.envp_[i] != nullptr; ++i) { + if (std::string(os_proc->startup_config_.envp_[i]) == "LCM_ALIVE_INTERFACE_PATH=/lifecycle_health_comp_a") { + found = true; + break; + } + } + EXPECT_TRUE(found) << "LCM_ALIVE_INTERFACE_PATH not found in supervised component envp"; +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessConfigurationNoAliveInterfaceForNative) +{ + RecordProperty("Description", "Native components do not get LCM_ALIVE_INTERFACE_PATH injected."); + + IdentifierHash pg_name{"MainPG"}; + auto result = adapter_.getOsProcessConfiguration(pg_name, 1U); + ASSERT_TRUE(result.has_value()); + const auto* os_proc = *result; + + for (size_t i = 0; os_proc->startup_config_.envp_[i] != nullptr; ++i) { + EXPECT_THAT(std::string(os_proc->startup_config_.envp_[i]).find("LCM_ALIVE_INTERFACE_PATH"), + Eq(std::string::npos)) + << "Native component should not have LCM_ALIVE_INTERFACE_PATH"; + } +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessDependenciesMapsComponentDependsOn) +{ + RecordProperty("Description", "getOsProcessDependencies maps component depends_on to legacy Dependency structs."); + + IdentifierHash pg_name{"MainPG"}; + + auto result = adapter_.getOsProcessDependencies(pg_name, 1U); + + ASSERT_TRUE(result.has_value()); + const auto* deps = *result; + ASSERT_THAT(deps->size(), Eq(1U)); + EXPECT_THAT((*deps)[0].target_process_id_, Eq(IdentifierHash{"comp_a"})); + EXPECT_THAT((*deps)[0].os_process_index_, Eq(0U)); + EXPECT_THAT((*deps)[0].process_state_, Eq(score::lcm::ProcessState::kRunning)); +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessDependenciesEmptyForComponentWithNoDeps) +{ + RecordProperty("Description", "Component with no depends_on has an empty dependency list."); + + IdentifierHash pg_name{"MainPG"}; + + auto result = adapter_.getOsProcessDependencies(pg_name, 0U); + + ASSERT_TRUE(result.has_value()); + const auto* deps = *result; + EXPECT_TRUE(deps->empty()); +} + +TEST_F(ConfigurationAdapterTest, GetNumberOfOsProcessesReturnsComponentCount) +{ + RecordProperty("Description", "getNumberOfOsProcesses returns the number of components."); + + auto result = adapter_.getNumberOfOsProcesses(IdentifierHash{"MainPG"}); + + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(2U)); +} + +TEST_F(ConfigurationAdapterTest, GetSoftwareClusterReturnsDefault) +{ + RecordProperty("Description", "getSoftwareCluster returns the default software cluster."); + + auto result = adapter_.getSoftwareCluster(IdentifierHash{"MainPG"}); + + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(IdentifierHash{"DefaultSoftwareCluster"})); +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessConfigurationReturnsNulloptForInvalidIndex) +{ + RecordProperty("Description", "Out-of-range index returns nullopt."); + + auto result = adapter_.getOsProcessConfiguration(IdentifierHash{"MainPG"}, 99U); + + EXPECT_FALSE(result.has_value()); +} + +TEST_F(ConfigurationAdapterTest, GetOsProcessConfigurationReturnsNulloptForUnknownPG) +{ + RecordProperty("Description", "Unknown process group name returns nullopt."); + + auto result = adapter_.getOsProcessConfiguration(IdentifierHash{"NonExistent"}, 0U); + + EXPECT_FALSE(result.has_value()); +} + +TEST_F(ConfigurationAdapterTest, OffStateReturnsProcessIndexesListEmpty) +{ + RecordProperty("Description", "The Off state has no process indexes."); + + score::lcm::internal::ProcessGroupStateID off_id{ + IdentifierHash{"MainPG"}, IdentifierHash{"MainPG/Off"}}; + + auto result = adapter_.getProcessIndexesList(off_id); + + ASSERT_TRUE(result.has_value()); + EXPECT_TRUE((**result).empty()); +} + +} // namespace +} // namespace score::mw::launch_manager::configuration diff --git a/scripts/config_mapping/unit_tests.py b/scripts/config_mapping/unit_tests.py index 33635d2ec..e2bdfa80d 100644 --- a/scripts/config_mapping/unit_tests.py +++ b/scripts/config_mapping/unit_tests.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 -from scripts.config_mapping.lifecycle_config import preprocess_defaults +from scripts.config_mapping.lifecycle_config import preprocess_defaults, gen_config, score_defaults import json +import os +import tempfile def test_preprocessing_basic(): @@ -141,3 +143,241 @@ def test_preprocessing_basic(): assert preprocessed_config == expected_config, ( "Preprocessed config does not match expected config." ) + + +def _make_preprocessed_config(): + """Helper that returns a fully-preprocessed config suitable for gen_config().""" + input_config = { + "schema_version": 1, + "components": { + "app_a": { + "description": "First app", + "component_properties": { + "binary_name": "app_a_bin", + "application_profile": { + "application_type": "Reporting_And_Supervised", + "is_self_terminating": False, + "alive_supervision": { + "reporting_cycle": 0.5, + "failed_cycles_tolerance": 2, + "min_indications": 1, + "max_indications": 3, + }, + }, + "depends_on": [], + "process_arguments": ["--flag"], + "ready_condition": {"process_state": "Running"}, + }, + "deployment_config": { + "bin_dir": "/opt/apps", + }, + }, + "app_b": { + "description": "Second app", + "component_properties": { + "binary_name": "app_b_bin", + "application_profile": { + "application_type": "Native", + "is_self_terminating": True, + }, + "depends_on": ["app_a"], + "process_arguments": [], + "ready_condition": {"process_state": "Terminated"}, + }, + "deployment_config": { + "bin_dir": "/opt/apps", + }, + }, + }, + "run_targets": { + "Startup": { + "description": "Initial", + "depends_on": ["app_a"], + "transition_timeout": 5, + "recovery_action": { + "switch_run_target": {"run_target": "fallback_run_target"} + }, + }, + }, + "initial_run_target": "Startup", + "fallback_run_target": { + "description": "Safe state", + "depends_on": [], + "transition_timeout": 1.5, + "recovery_action": { + "switch_run_target": {"run_target": "fallback_run_target"} + }, + }, + "alive_supervision": {"evaluation_cycle": 0.5}, + "watchdog": { + "device_file_path": "/dev/watchdog", + "max_timeout": 2, + "deactivate_on_shutdown": True, + "require_magic_close": False, + }, + } + config = preprocess_defaults(score_defaults, input_config) + config["schema_version"] = input_config["schema_version"] + config["initial_run_target"] = input_config["initial_run_target"] + config["fallback_run_target"] = preprocess_defaults( + score_defaults, input_config + )["fallback_run_target"] + return config + + +def _run_gen_config(config): + """Run gen_config into a temp directory and return the parsed JSON output.""" + with tempfile.TemporaryDirectory() as tmpdir: + gen_config(tmpdir, config) + output_path = os.path.join(tmpdir, "launch_manager_config.json") + with open(output_path) as f: + return json.load(f) + + +def test_gen_config_produces_single_file(): + """gen_config writes exactly one file named launch_manager_config.json.""" + config = _make_preprocessed_config() + with tempfile.TemporaryDirectory() as tmpdir: + gen_config(tmpdir, config) + files = os.listdir(tmpdir) + assert files == ["launch_manager_config.json"], ( + f"Expected single output file, got: {files}" + ) + + +def test_gen_config_top_level_structure(): + """Output contains all required top-level keys matching new_lm_flatcfg.fbs.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + required_keys = { + "schema_version", + "components", + "run_targets", + "initial_run_target", + "fallback_run_target", + "alive_supervision", + "watchdog", + } + assert required_keys.issubset(output.keys()), ( + f"Missing top-level keys: {required_keys - output.keys()}" + ) + + +def test_gen_config_components_are_list(): + """Components are emitted as a list (not a dict), each with a 'name' field.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + assert isinstance(output["components"], list) + names = [c["name"] for c in output["components"]] + assert "app_a" in names + assert "app_b" in names + + +def test_gen_config_component_fields(): + """Each component has the expected nested structure.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + comp = next(c for c in output["components"] if c["name"] == "app_a") + + assert comp["description"] == "First app" + assert comp["component_properties"]["binary_name"] == "app_a_bin" + assert comp["component_properties"]["application_profile"]["application_type"] == "Reporting_And_Supervised" + assert comp["component_properties"]["application_profile"]["is_self_terminating"] is False + assert comp["component_properties"]["application_profile"]["alive_supervision"]["reporting_cycle"] == 0.5 + assert comp["component_properties"]["process_arguments"] == ["--flag"] + assert comp["component_properties"]["ready_condition"]["process_state"] == "Running" + + assert comp["deployment_config"]["ready_timeout"] == 0.5 + assert comp["deployment_config"]["shutdown_timeout"] == 0.5 + assert comp["deployment_config"]["bin_dir"] == "/opt/apps" + assert "sandbox" in comp["deployment_config"] + assert comp["deployment_config"]["sandbox"]["uid"] == 1000 + assert comp["deployment_config"]["sandbox"]["scheduling_policy"] == "OTHER" + + +def test_gen_config_run_targets_are_list(): + """Run targets are emitted as a list with a 'name' field.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + assert isinstance(output["run_targets"], list) + rt = output["run_targets"][0] + assert rt["name"] == "Startup" + assert rt["transition_timeout"] == 5 + assert rt["recovery_action"]["run_target"] == "fallback_run_target" + assert rt["depends_on"] == ["app_a"] + + +def test_gen_config_fallback_run_target(): + """Fallback run target is a flat object with transition_timeout.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + frt = output["fallback_run_target"] + assert frt["transition_timeout"] == 1.5 + + +def test_gen_config_alive_supervision(): + """Alive supervision section has evaluation_cycle in seconds.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + assert output["alive_supervision"]["evaluation_cycle"] == 0.5 + + +def test_gen_config_watchdog(): + """Watchdog section contains all required fields.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + wd = output["watchdog"] + assert wd["device_file_path"] == "/dev/watchdog" + assert wd["max_timeout"] == 2 + assert wd["deactivate_on_shutdown"] is True + assert wd["require_magic_close"] is False + + +def test_gen_config_no_watchdog_when_empty(): + """When watchdog config has no required fields, it is omitted from output.""" + config = _make_preprocessed_config() + config["watchdog"] = {} + output = _run_gen_config(config) + + assert "watchdog" not in output + + +def test_gen_config_env_vars_as_key_value_list(): + """Environmental variables are emitted as a list of {key, value} objects.""" + config = _make_preprocessed_config() + config["components"]["app_a"]["deployment_config"]["environmental_variables"] = { + "FOO": "bar", + "BAZ": "qux", + } + output = _run_gen_config(config) + + comp = next(c for c in output["components"] if c["name"] == "app_a") + env_vars = comp["deployment_config"]["environmental_variables"] + assert isinstance(env_vars, list) + keys = {ev["key"] for ev in env_vars} + assert keys == {"FOO", "BAZ"} + + +def test_gen_config_native_app_no_alive_supervision(): + """Native application type does not include alive_supervision in output.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + native_comp = next(c for c in output["components"] if c["name"] == "app_b") + assert "alive_supervision" not in native_comp["component_properties"]["application_profile"] + + +def test_gen_config_depends_on_preserved(): + """Component depends_on is preserved in the output.""" + config = _make_preprocessed_config() + output = _run_gen_config(config) + + comp_b = next(c for c in output["components"] if c["name"] == "app_b") + assert comp_b["component_properties"]["depends_on"] == ["app_a"] From ea6a8840ad77cb8d3dae885c4bdb05c044afdf84 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Fri, 19 Jun 2026 14:24:42 +0200 Subject: [PATCH 4/7] applied suggestions from review --- examples/demo_verification/test_examples.py | 2 +- .../src/alive_monitor/details/factory/BUILD | 1 + .../details/factory/FlatCfgFactory.cpp | 57 ++--- .../details/factory/FlatCfgFactory.hpp | 7 +- score/launch_manager/daemon/src/common/BUILD | 8 + .../src/common/alive_interface_path.hpp | 36 +++ .../daemon/src/configuration/BUILD | 3 +- .../daemon/src/configuration/config.hpp | 3 +- .../configuration/configuration_adapter.cpp | 240 +++++++++--------- .../configuration/configuration_adapter.hpp | 6 + .../configuration_adapter_UT.cpp | 6 +- .../details/flatbuffer_config_loader_UT.cpp | 35 ++- .../details/flatbuffer_type_converters.cpp | 6 +- .../details/flatbuffer_type_converters_UT.cpp | 36 ++- .../configuration/details/new_lm_flatcfg.fbs | 6 +- score/launch_manager/daemon/src/main.cpp | 26 +- .../docs/user_guide/getting_started.rst | 154 +++++++++++ scripts/config_mapping/config.bzl | 2 +- scripts/config_mapping/integration_tests.py | 4 +- scripts/config_mapping/lifecycle_config.py | 29 ++- ...manager_config.json => lm_config_gen.json} | 15 +- ...manager_config.json => lm_config_gen.json} | 3 +- ...manager_config.json => lm_config_gen.json} | 0 ...manager_config.json => lm_config_gen.json} | 12 +- ...manager_config.json => lm_config_gen.json} | 18 +- scripts/config_mapping/unit_tests.py | 3 +- .../complex_monitoring/complex_monitoring.py | 2 +- .../crash_on_startup/crash_on_startup.py | 2 +- .../test_incorrect_config_non_reporting.py | 2 +- .../process_crash_monitoring.py | 2 +- .../process_launch_args.py | 2 +- tests/integration/smoke/smoke.py | 2 +- .../switch_run_target/switch_run_target.py | 2 +- 33 files changed, 464 insertions(+), 268 deletions(-) create mode 100644 score/launch_manager/daemon/src/common/alive_interface_path.hpp rename score/launch_manager/daemon/src/configuration/{details => }/configuration_adapter_UT.cpp (98%) create mode 100644 score/launch_manager/docs/user_guide/getting_started.rst rename scripts/config_mapping/tests/basic_test/expected_output/{launch_manager_config.json => lm_config_gen.json} (96%) rename scripts/config_mapping/tests/empty_health_config_test/expected_output/{launch_manager_config.json => lm_config_gen.json} (96%) rename scripts/config_mapping/tests/empty_lm_config_test/expected_output/{launch_manager_config.json => lm_config_gen.json} (100%) rename scripts/config_mapping/tests/health_config_test/expected_output/{launch_manager_config.json => lm_config_gen.json} (95%) rename scripts/config_mapping/tests/lm_config_test/expected_output/{launch_manager_config.json => lm_config_gen.json} (96%) diff --git a/examples/demo_verification/test_examples.py b/examples/demo_verification/test_examples.py index 1a1e28d92..73f4a7dee 100644 --- a/examples/demo_verification/test_examples.py +++ b/examples/demo_verification/test_examples.py @@ -71,7 +71,7 @@ def test_examples(target, setup_test, remote_test_dir): lmcontrol_path = str(remote_test_dir / "lmcontrol") _step("Starting launch manager (Startup)") - lm_proc = target.execute_async(lm_path, cwd=str(remote_test_dir)) + lm_proc = target.execute_async(lm_path, args=["-c", "etc/lifecycle_demo_test_gen.bin"], cwd=str(remote_test_dir)) time.sleep(1.0) assert lm_proc.is_running(), "Launch manager exited unexpectedly during Startup" diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD b/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD index 25092b12c..a91475f42 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/BUILD @@ -76,6 +76,7 @@ cc_library( "//score/launch_manager/daemon/src/alive_monitor/details/supervision:supervision_cfg", "//score/launch_manager/daemon/src/alive_monitor/details/timers:time_conversion", "//score/launch_manager/daemon/src/alive_monitor/details/timers:timers_os_clock", + "//score/launch_manager/daemon/src/common:alive_interface_path", "//score/launch_manager/daemon/src/common:identifier_hash", "//score/launch_manager/daemon/src/configuration:config", ] + select({ diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp index 594acfd31..4c1952b67 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp @@ -16,6 +16,7 @@ #include #include +#include "score/mw/launch_manager/common/alive_interface_path.hpp" #include "score/mw/launch_manager/common/identifier_hash.hpp" #include "score/mw/launch_manager/alive_monitor/details/factory/IPhmFactory.hpp" #include "score/mw/launch_manager/alive_monitor/details/factory/StaticConfig.hpp" @@ -39,7 +40,6 @@ namespace factory namespace { -static constexpr const char* kLogPrefix{"Factory for FlatCfg AR24-11:"}; bool isSupervisedType(score::mw::launch_manager::configuration::ApplicationType app_type) { @@ -96,19 +96,19 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro break; } - logger_r.LogDebug() << kLogPrefix << "Successfully created Process States:" << comp->name; + logger_r.LogDebug() << "Successfully created Process States:" << comp->name; } } catch (const std::exception& f_exception_r) { isSuccess = false; - logger_r.LogError() << kLogPrefix << "Could not create Process States due to exception:" + logger_r.LogError() << "Could not create Process States due to exception:" << std::string_view{f_exception_r.what()}; } if (isSuccess) { - logger_r.LogDebug() << kLogPrefix << "Number of constructed Process States:" + logger_r.LogDebug() << "Number of constructed Process States:" << static_cast(f_processStates_r.size()); } else @@ -118,7 +118,7 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro f_processStateReader_r.deregisterProcessState(processState_r.getProcessId()); } f_processStates_r.clear(); - logger_r.LogError() << kLogPrefix << "Could not create all necessary Process States."; + logger_r.LogError() << "Could not create all necessary Process States."; } return isSuccess; @@ -137,7 +137,7 @@ bool FlatCfgFactory::initIpcServerWithUidBasedAccess(ifappl::CheckpointIpcServer const uid_t uid = static_cast(f_uid); if (!f_ipcServer_r.setAccessRights(uid)) { - logger_r.LogError() << kLogPrefix << "Could not set ACL permissions (r/w for uid" << uid + logger_r.LogError() << "Could not set ACL permissions (r/w for uid" << uid << ") for Monitor interface IPC with path:" << f_ipcPath_r; return false; } @@ -153,20 +153,18 @@ bool FlatCfgFactory::createMonitorIfIpcs(std::vectorname; + const std::string pathInterface = score::lcm::internal::aliveInterfacePath(comp->name); f_interfaceIpcs_r.emplace_back(); const std::int32_t configuredUid = static_cast(comp->deployment_config.sandbox.uid); isSuccess = initIpcServerWithUidBasedAccess(f_interfaceIpcs_r.back(), pathInterface, configuredUid); if (isSuccess) { - logger_r.LogDebug() << kLogPrefix - << "Successfully created Monitor interface IPC with path:" << pathInterface; + logger_r.LogDebug() << "Successfully created Monitor interface IPC with path:" << pathInterface; } else { - logger_r.LogError() << kLogPrefix - << "Could not create Monitor interface IPC with path:" << pathInterface; + logger_r.LogError() << "Could not create Monitor interface IPC with path:" << pathInterface; break; } } @@ -174,19 +172,19 @@ bool FlatCfgFactory::createMonitorIfIpcs(std::vector(f_interfaceIpcs_r.size()); } else { f_interfaceIpcs_r.clear(); - logger_r.LogError() << kLogPrefix << "Could not create all necessary Monitor interface IPCs."; + logger_r.LogError() << "Could not create all necessary Monitor interface IPCs."; } return isSuccess; @@ -206,19 +204,18 @@ bool FlatCfgFactory::createMonitorIf(std::vector& f_int f_interfaces_r.emplace_back(interfaceIpc, interfaceIpc.getPath().data()); f_processStates_r.at(static_cast(index)).attachObserver(f_interfaces_r.back()); - logger_r.LogDebug() << kLogPrefix - << "Successfully created MonitorInterface:" << f_interfaces_r.back().getInterfaceName(); + logger_r.LogDebug() << "Successfully created MonitorInterface:" << f_interfaces_r.back().getInterfaceName(); index++; } - logger_r.LogDebug() << kLogPrefix << "Number of constructed Monitor interfaces:" + logger_r.LogDebug() << "Number of constructed Monitor interfaces:" << static_cast(f_interfaces_r.size()); } catch (const std::exception& f_exception_r) { isSuccess = false; f_interfaces_r.clear(); - logger_r.LogError() << kLogPrefix << "Could not create all necessary Monitor interfaces due to exception:" + logger_r.LogError() << "Could not create all necessary Monitor interfaces due to exception:" << std::string_view{f_exception_r.what()}; } @@ -245,26 +242,26 @@ bool FlatCfgFactory::createSupervisionCheckpoints(std::vector(f_checkpoints_r.size()); } else { f_checkpoints_r.clear(); - logger_r.LogError() << kLogPrefix << "Could not create all necessary supervision checkpoints."; + logger_r.LogError() << "Could not create all necessary supervision checkpoints."; } return isSuccess; @@ -280,6 +277,8 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ try { f_alive_r.reserve(supervised_components_.size()); + alive_cfg_names_.clear(); + alive_cfg_names_.reserve(supervised_components_.size()); for (size_t idx = 0; idx < supervised_components_.size(); ++idx) { @@ -290,7 +289,7 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ continue; } - const std::string nameCfgAlive = comp->name + "_alive_supervision"; + alive_cfg_names_.emplace_back(comp->name + "_alive_supervision"); saf::timers::NanoSecondType aliveReferenceCycleCfg{ timers::TimeConversion::convertMilliSecToNanoSec(static_cast(alive_sup->reporting_cycle_ms))}; uint32_t minAliveIndicationsCfg = alive_sup->min_indications.value_or(0U); @@ -302,7 +301,7 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ supervision::AliveSupervisionCfg aliveSupCfg{ f_checkpoints_r.at(idx)}; - aliveSupCfg.cfgName_p = nameCfgAlive.c_str(); + aliveSupCfg.cfgName_p = alive_cfg_names_.back().c_str(); aliveSupCfg.aliveReferenceCycle = aliveReferenceCycleCfg; aliveSupCfg.minAliveIndications = minAliveIndicationsCfg; aliveSupCfg.maxAliveIndications = maxAliveIndicationsCfg; @@ -318,28 +317,26 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ f_processStates_r.at(idx).attachObserver(f_alive_r.back()); - logger_r.LogDebug() << kLogPrefix << "Successfully created alive supervision worker object:" + logger_r.LogDebug() << "Successfully created alive supervision worker object:" << f_alive_r.back().getConfigName(); } } catch (const std::exception& f_exception_r) { isSuccess = false; - logger_r.LogError() << kLogPrefix - << "Could not create all necessary alive supervision " + logger_r.LogError() << "Could not create all necessary alive supervision " "worker objects, due to exception:" << std::string_view{f_exception_r.what()}; } if (isSuccess) { - logger_r.LogDebug() << kLogPrefix - << "Number of constructed alive supervisions:" << static_cast(f_alive_r.size()); + logger_r.LogDebug() << "Number of constructed alive supervisions:" << static_cast(f_alive_r.size()); } else { f_alive_r.clear(); - logger_r.LogError() << kLogPrefix << "Could not create all necessary alive supervision worker objects"; + logger_r.LogError() << "Could not create all necessary alive supervision worker objects"; } return isSuccess; diff --git a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp index d7594ce1c..e58d8f82e 100644 --- a/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp +++ b/score/launch_manager/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp @@ -111,12 +111,17 @@ class FlatCfgFactory : public IPhmFactory /// @brief The buffer configuration for constructing supervision objects const factory::MachineConfigFactory::SupervisionBufferConfig& bufferConfig_r; - /// Pointer to the unified configuration (not owned) + /// Non-owning pointer to the unified configuration. Must outlive this factory — + /// typically the Config lives in main() and the factory is destroyed before it. const score::mw::launch_manager::configuration::Config* config_; /// Filtered list of supervised components (pointers into config_->components()) std::vector supervised_components_; + /// Stable storage for alive supervision config names, so that raw const char* pointers + /// passed via AliveSupervisionCfg::cfgName_p remain valid for the factory's lifetime. + std::vector alive_cfg_names_; + /// Logger object for logging messages logging::PhmLogger& logger_r; }; diff --git a/score/launch_manager/daemon/src/common/BUILD b/score/launch_manager/daemon/src/common/BUILD index 9aa2ba0d2..4d975c35f 100644 --- a/score/launch_manager/daemon/src/common/BUILD +++ b/score/launch_manager/daemon/src/common/BUILD @@ -51,6 +51,14 @@ cc_library( }), ) +cc_library( + name = "alive_interface_path", + hdrs = ["alive_interface_path.hpp"], + include_prefix = "score/mw/launch_manager/common", + strip_include_prefix = "/score/launch_manager/daemon/src/common", + visibility = ["//score:__subpackages__"], +) + cc_library( name = "constants", hdrs = ["constants.hpp"], diff --git a/score/launch_manager/daemon/src/common/alive_interface_path.hpp b/score/launch_manager/daemon/src/common/alive_interface_path.hpp new file mode 100644 index 000000000..da9b7b401 --- /dev/null +++ b/score/launch_manager/daemon/src/common/alive_interface_path.hpp @@ -0,0 +1,36 @@ +/******************************************************************************** + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +#ifndef ALIVE_INTERFACE_PATH_HPP_INCLUDED +#define ALIVE_INTERFACE_PATH_HPP_INCLUDED + +#include + +namespace score +{ +namespace lcm +{ +namespace internal +{ + +/// Returns the IPC socket path for the alive monitoring interface of a component. +inline std::string aliveInterfacePath(const std::string& component_name) +{ + return "/lifecycle_health_" + component_name; +} + +} // namespace internal +} // namespace lcm +} // namespace score + +#endif // ALIVE_INTERFACE_PATH_HPP_INCLUDED diff --git a/score/launch_manager/daemon/src/configuration/BUILD b/score/launch_manager/daemon/src/configuration/BUILD index 1555bb630..9de492f90 100644 --- a/score/launch_manager/daemon/src/configuration/BUILD +++ b/score/launch_manager/daemon/src/configuration/BUILD @@ -124,6 +124,7 @@ cc_library( ":config", ":config_loader", ":flatbuffer_config_loader", + "//score/launch_manager/daemon/src/common:alive_interface_path", "//score/launch_manager/daemon/src/common:constants", "//score/launch_manager/daemon/src/common:identifier_hash", "//score/launch_manager/daemon/src/common:log", @@ -136,7 +137,7 @@ cc_library( cc_test( name = "configuration_adapter_UT", - srcs = ["details/configuration_adapter_UT.cpp"], + srcs = ["configuration_adapter_UT.cpp"], visibility = ["//tests:__subpackages__"], deps = [ ":configuration_adapter", diff --git a/score/launch_manager/daemon/src/configuration/config.hpp b/score/launch_manager/daemon/src/configuration/config.hpp index 49810d483..9a3c809c0 100644 --- a/score/launch_manager/daemon/src/configuration/config.hpp +++ b/score/launch_manager/daemon/src/configuration/config.hpp @@ -59,7 +59,6 @@ struct ReadyCondition struct ComponentProperties { - std::string binary_name; ApplicationProfile application_profile; std::vector depends_on; std::vector process_arguments; @@ -152,7 +151,7 @@ struct DeploymentConfig uint32_t ready_timeout_ms{}; uint32_t shutdown_timeout_ms{}; Environment environmental_variables; - std::string bin_dir; + std::string executable_path; std::string working_dir; std::optional ready_recovery_action; // Currently only SwitchRunTargetAction is supported here, RestartAction to be added in the future diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp index 9b6f13b48..49738e399 100644 --- a/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.cpp @@ -12,6 +12,7 @@ ********************************************************************************/ #include "score/mw/launch_manager/configuration/configuration_adapter.hpp" +#include "score/mw/launch_manager/common/alive_interface_path.hpp" #include "score/mw/launch_manager/common/log.hpp" #include "score/mw/launch_manager/osal/num_cores.hpp" @@ -46,14 +47,6 @@ score::lcm::internal::osal::CommsType ConfigurationAdapter::mapApplicationType( } bool ConfigurationAdapter::initialize(const Config& config) { - LM_LOG_DEBUG() << "Loading LCM Configurations..."; - - const char* env_val = getenv("ECUCFG_ENV_VAR_ROOTFOLDER"); - if (!env_val || strlen(env_val) == 0) { - setenv("ECUCFG_ENV_VAR_ROOTFOLDER", "/opt/internal/launch_manager/etc/ecu-cfg", 1); - } - LM_LOG_DEBUG() << "ECUCFG_ENV_VAR_ROOTFOLDER set successfully"; - return buildFromConfig(config); } @@ -74,128 +67,106 @@ void ConfigurationAdapter::deinitialize() { } } -bool ConfigurationAdapter::buildFromConfig(const Config& config) { - const std::string initial_run_target_name = std::string(config.initialRunTarget()); - - ProcessGroup pg; - const IdentifierHash pg_name{"MainPG"}; - pg.name_ = pg_name; - pg.sw_cluster_ = IdentifierHash{"DefaultSoftwareCluster"}; - pg.off_state_ = IdentifierHash{"MainPG/Off"}; - - const auto& fallback = config.fallbackRunTarget(); - const auto& run_targets = config.runTargets(); - - IdentifierHash recovery_state{"Recovery"}; - for (const auto& rt : run_targets) { - if (rt.recovery_action.run_target == "fallback_run_target") { - recovery_state = IdentifierHash{std::string("MainPG/") + "fallback_run_target"}; - break; - } +OsProcess ConfigurationAdapter::buildOsProcess(const ComponentConfig& comp, uint32_t process_index) const { + OsProcess os_process{}; + os_process.process_id_ = IdentifierHash{comp.name}; + os_process.process_number_ = process_index; + + auto& startup = os_process.startup_config_; + const auto& deploy = comp.deployment_config; + const auto& props = comp.component_properties; + + startup.executable_path_ = deploy.executable_path; + startup.short_name_ = comp.name; + + startup.uid_ = deploy.sandbox.uid; + startup.gid_ = deploy.sandbox.gid; + startup.supplementary_gids_ = deploy.sandbox.supplementary_group_ids; + startup.security_policy_ = deploy.sandbox.security_policy.value_or(""); + startup.scheduling_policy_ = deploy.sandbox.scheduling_policy; + startup.scheduling_priority_ = deploy.sandbox.scheduling_priority; + startup.cpu_mask_ = kDefaultProcessorAffinityMask(); + + startup.resource_limits_.stack_ = 0U; + startup.resource_limits_.cpu_ = 0U; + startup.resource_limits_.data_ = 0U; + startup.resource_limits_.as_ = 0U; + if (deploy.sandbox.max_memory_usage.has_value()) { + startup.resource_limits_.as_ = *deploy.sandbox.max_memory_usage; } - pg.recovery_state_ = recovery_state; - std::map component_to_process_index; - uint32_t process_index = 0; + startup.comms_type_ = mapApplicationType(props.application_profile.application_type); - for (const auto& comp : config.components()) { - OsProcess os_process{}; - os_process.process_id_ = IdentifierHash{comp.name}; - os_process.process_number_ = process_index; - - auto& startup = os_process.startup_config_; - const auto& deploy = comp.deployment_config; - const auto& props = comp.component_properties; + // strdup() returns nullptr on OOM. On this embedded target, OOM during daemon + // startup is unrecoverable — the OS will terminate the process. + size_t arg_index = 0U; + startup.argv_[arg_index++] = strdup(startup.executable_path_.c_str()); + size_t max_args = std::min(props.process_arguments.size(), + static_cast(score::lcm::internal::kMaxArg)); + for (size_t i = 0U; i < max_args; ++i) { + startup.argv_[arg_index++] = strdup(props.process_arguments[i].c_str()); + } - std::string exec_path = deploy.bin_dir; - if (!exec_path.empty() && exec_path.back() != '/') { - exec_path += '/'; - } - exec_path += props.binary_name; - startup.executable_path_ = exec_path; - startup.short_name_ = comp.name; - - startup.uid_ = deploy.sandbox.uid; - startup.gid_ = deploy.sandbox.gid; - startup.supplementary_gids_ = deploy.sandbox.supplementary_group_ids; - startup.security_policy_ = deploy.sandbox.security_policy.value_or(""); - startup.scheduling_policy_ = deploy.sandbox.scheduling_policy; - startup.scheduling_priority_ = deploy.sandbox.scheduling_priority; - startup.cpu_mask_ = kDefaultProcessorAffinityMask(); - - startup.resource_limits_.stack_ = 0U; - startup.resource_limits_.cpu_ = 0U; - startup.resource_limits_.data_ = 0U; - startup.resource_limits_.as_ = 0U; - if (deploy.sandbox.max_memory_usage.has_value()) { - startup.resource_limits_.as_ = *deploy.sandbox.max_memory_usage; - } + size_t env_index = 0U; + size_t max_env = std::min(deploy.environmental_variables.size(), + static_cast(score::lcm::internal::kMaxEnv)); + size_t env_count = 0; + for (const auto& ev : deploy.environmental_variables) { + if (env_count >= max_env) break; + std::string env_str = std::string(ev.key()) + "=" + std::string(ev.value()); + startup.envp_[env_index++] = strdup(env_str.c_str()); + ++env_count; + } - startup.comms_type_ = mapApplicationType(props.application_profile.application_type); + bool is_sup = (props.application_profile.application_type == ApplicationType::ReportingAndSupervised || + props.application_profile.application_type == ApplicationType::StateManager); + if (is_sup && env_index < static_cast(score::lcm::internal::kMaxEnv)) { + std::string iface_path = "LCM_ALIVE_INTERFACE_PATH=" + score::lcm::internal::aliveInterfacePath(comp.name); + startup.envp_[env_index++] = strdup(iface_path.c_str()); + } - size_t arg_index = 0U; - startup.argv_[arg_index] = strdup(startup.executable_path_.c_str()); - ++arg_index; - size_t max_args = std::min(props.process_arguments.size(), - static_cast(score::lcm::internal::kMaxArg)); - for (size_t i = 0U; i < max_args; ++i) { - startup.argv_[arg_index++] = strdup(props.process_arguments[i].c_str()); - } + startup.envp_[env_index] = nullptr; - size_t env_index = 0U; - size_t max_env = std::min(deploy.environmental_variables.size(), - static_cast(score::lcm::internal::kMaxEnv)); - size_t env_count = 0; - for (const auto& ev : deploy.environmental_variables) { - if (env_count >= max_env) break; - std::string env_str = std::string(ev.key()) + "=" + std::string(ev.value()); - startup.envp_[env_index++] = strdup(env_str.c_str()); - ++env_count; - } + auto& pgm = os_process.pgm_config_; + pgm.is_self_terminating_ = props.application_profile.is_self_terminating; + pgm.startup_timeout_ms_ = std::chrono::milliseconds(deploy.ready_timeout_ms); + pgm.termination_timeout_ms_ = std::chrono::milliseconds(deploy.shutdown_timeout_ms); + pgm.execution_error_code_ = kDefaultProcessExecutionError; + pgm.number_of_restart_attempts = 0U; + if (deploy.ready_recovery_action.has_value()) { + pgm.number_of_restart_attempts = deploy.ready_recovery_action->number_of_attempts; + } - bool is_sup = (props.application_profile.application_type == ApplicationType::ReportingAndSupervised || - props.application_profile.application_type == ApplicationType::StateManager); - if (is_sup && env_index < static_cast(score::lcm::internal::kMaxEnv)) { - std::string iface_path = "LCM_ALIVE_INTERFACE_PATH=/lifecycle_health_" + comp.name; - startup.envp_[env_index++] = strdup(iface_path.c_str()); + for (const auto& dep_name : props.depends_on) { + Dependency dep{}; + if (props.ready_condition.has_value()) { + dep.process_state_ = (props.ready_condition->process_state == ProcessState::Running) + ? score::lcm::ProcessState::kRunning + : score::lcm::ProcessState::kTerminated; + } else { + dep.process_state_ = score::lcm::ProcessState::kRunning; } + dep.target_process_id_ = IdentifierHash{dep_name}; + os_process.dependencies_.push_back(dep); + } - startup.envp_[env_index] = nullptr; - - auto& pgm = os_process.pgm_config_; - pgm.is_self_terminating_ = props.application_profile.is_self_terminating; - pgm.startup_timeout_ms_ = std::chrono::milliseconds(deploy.ready_timeout_ms); - pgm.termination_timeout_ms_ = std::chrono::milliseconds(deploy.shutdown_timeout_ms); - pgm.execution_error_code_ = kDefaultProcessExecutionError; - pgm.number_of_restart_attempts = 0U; - if (deploy.ready_recovery_action.has_value()) { - pgm.number_of_restart_attempts = deploy.ready_recovery_action->number_of_attempts; - } + return os_process; +} - for (const auto& dep_name : props.depends_on) { - Dependency dep{}; - if (props.ready_condition.has_value()) { - dep.process_state_ = (props.ready_condition->process_state == ProcessState::Running) - ? score::lcm::ProcessState::kRunning - : score::lcm::ProcessState::kTerminated; - } else { - dep.process_state_ = score::lcm::ProcessState::kRunning; - } - dep.target_process_id_ = IdentifierHash{dep_name}; - os_process.dependencies_.push_back(dep); - } +std::vector ConfigurationAdapter::buildProcessGroupStates( + const Config& config, + const std::map& component_to_process_index) const { - component_to_process_index[comp.name] = process_index; - pg.processes_.push_back(std::move(os_process)); - ++process_index; - } + std::vector states; { ProcessGroupState off_state; off_state.name_ = IdentifierHash{"MainPG/Off"}; - pg.states_.push_back(off_state); + states.push_back(off_state); } + const auto& run_targets = config.runTargets(); + std::map run_target_by_name; for (const auto& rt : run_targets) { run_target_by_name[rt.name] = &rt; @@ -239,10 +210,11 @@ bool ConfigurationAdapter::buildFromConfig(const Config& config) { for (const auto& dep_name : rt.depends_on) { resolve_depends(dep_name, pgs.process_indexes_, visited); } - pg.states_.push_back(std::move(pgs)); + states.push_back(std::move(pgs)); } { + const auto& fallback = config.fallbackRunTarget(); ProcessGroupState fallback_state; fallback_state.name_ = IdentifierHash{"MainPG/fallback_run_target"}; for (const auto& comp_name : fallback.depends_on) { @@ -251,19 +223,53 @@ bool ConfigurationAdapter::buildFromConfig(const Config& config) { fallback_state.process_indexes_.push_back(it->second); } } - pg.states_.push_back(std::move(fallback_state)); + states.push_back(std::move(fallback_state)); } - for (auto& proc : pg.processes_) { + return states; +} + +void ConfigurationAdapter::resolveDependencyIndexes(std::vector& processes) { + for (auto& proc : processes) { for (auto& dep : proc.dependencies_) { - for (uint32_t idx = 0; idx < pg.processes_.size(); ++idx) { - if (pg.processes_[idx].process_id_ == dep.target_process_id_) { + for (uint32_t idx = 0; idx < processes.size(); ++idx) { + if (processes[idx].process_id_ == dep.target_process_id_) { dep.os_process_index_ = idx; break; } } } } +} + +bool ConfigurationAdapter::buildFromConfig(const Config& config) { + const std::string initial_run_target_name = std::string(config.initialRunTarget()); + + ProcessGroup pg; + const IdentifierHash pg_name{"MainPG"}; + pg.name_ = pg_name; + pg.sw_cluster_ = IdentifierHash{"DefaultSoftwareCluster"}; + pg.off_state_ = IdentifierHash{"MainPG/Off"}; + + IdentifierHash recovery_state{"Recovery"}; + for (const auto& rt : config.runTargets()) { + if (rt.recovery_action.run_target == "fallback_run_target") { + recovery_state = IdentifierHash{std::string("MainPG/") + "fallback_run_target"}; + break; + } + } + pg.recovery_state_ = recovery_state; + + std::map component_to_process_index; + uint32_t process_index = 0; + for (const auto& comp : config.components()) { + component_to_process_index[comp.name] = process_index; + pg.processes_.push_back(buildOsProcess(comp, process_index)); + ++process_index; + } + + pg.states_ = buildProcessGroupStates(config, component_to_process_index); + resolveDependencyIndexes(pg.processes_); process_groups_.push_back(std::move(pg)); process_group_names_.push_back(pg_name); diff --git a/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp index 941321845..b44a93beb 100644 --- a/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter.hpp @@ -15,6 +15,7 @@ #define CONFIGURATIONADAPTER_HPP_INCLUDED #include +#include #include #include #include @@ -99,6 +100,11 @@ class ConfigurationAdapter final { private: bool buildFromConfig(const Config& config); + OsProcess buildOsProcess(const ComponentConfig& comp, uint32_t process_index) const; + std::vector buildProcessGroupStates( + const Config& config, + const std::map& component_to_process_index) const; + static void resolveDependencyIndexes(std::vector& processes); score::lcm::internal::osal::CommsType mapApplicationType(ApplicationType app_type) const; diff --git a/score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp b/score/launch_manager/daemon/src/configuration/configuration_adapter_UT.cpp similarity index 98% rename from score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp rename to score/launch_manager/daemon/src/configuration/configuration_adapter_UT.cpp index b1e915792..960093a5a 100644 --- a/score/launch_manager/daemon/src/configuration/details/configuration_adapter_UT.cpp +++ b/score/launch_manager/daemon/src/configuration/configuration_adapter_UT.cpp @@ -34,14 +34,13 @@ Config makeMinimalConfig() ComponentConfig comp_a; comp_a.name = "comp_a"; comp_a.description = "Component A"; - comp_a.component_properties.binary_name = "comp_a_bin"; comp_a.component_properties.application_profile.application_type = ApplicationType::ReportingAndSupervised; comp_a.component_properties.application_profile.is_self_terminating = false; comp_a.component_properties.application_profile.alive_supervision = ComponentAliveSupervision{500, 2, 1, 3}; comp_a.component_properties.ready_condition = ReadyCondition{ProcessState::Running}; comp_a.deployment_config.ready_timeout_ms = 500; comp_a.deployment_config.shutdown_timeout_ms = 500; - comp_a.deployment_config.bin_dir = "/opt/apps"; + comp_a.deployment_config.executable_path = "/opt/apps/comp_a_bin"; comp_a.deployment_config.working_dir = "/tmp"; comp_a.deployment_config.sandbox.uid = 1000; comp_a.deployment_config.sandbox.gid = 1000; @@ -51,14 +50,13 @@ Config makeMinimalConfig() ComponentConfig comp_b; comp_b.name = "comp_b"; comp_b.description = "Component B"; - comp_b.component_properties.binary_name = "comp_b_bin"; comp_b.component_properties.application_profile.application_type = ApplicationType::Native; comp_b.component_properties.application_profile.is_self_terminating = true; comp_b.component_properties.depends_on = {"comp_a"}; comp_b.component_properties.ready_condition = ReadyCondition{ProcessState::Running}; comp_b.deployment_config.ready_timeout_ms = 1000; comp_b.deployment_config.shutdown_timeout_ms = 1000; - comp_b.deployment_config.bin_dir = "/opt/apps"; + comp_b.deployment_config.executable_path = "/opt/apps/comp_b_bin"; comp_b.deployment_config.working_dir = "/tmp"; comp_b.deployment_config.sandbox.uid = 1000; comp_b.deployment_config.sandbox.gid = 1000; diff --git a/score/launch_manager/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp b/score/launch_manager/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp index 74eeebbb9..db40ae26d 100644 --- a/score/launch_manager/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp +++ b/score/launch_manager/daemon/src/configuration/details/flatbuffer_config_loader_UT.cpp @@ -63,21 +63,20 @@ ::flatbuffers::Offset buildDefaultSandbox(::flatbuffers::FlatBuffer ::flatbuffers::Offset buildDefaultComponentProperties(::flatbuffers::FlatBufferBuilder& fbb) { - auto bin_name = fbb.CreateString("default_bin"); auto app_profile = fb::CreateApplicationProfile(fbb, fb::ApplicationType::Native, false); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); return fb::CreateComponentProperties( - fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); + fbb, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); } ::flatbuffers::Offset buildDefaultDeploymentConfig(::flatbuffers::FlatBufferBuilder& fbb) { - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/default_bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); return fb::CreateDeploymentConfig( fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, - bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); } ::flatbuffers::Offset buildDefaultComponent( @@ -195,20 +194,19 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponent) fbb, 0.5 /*reporting_cycle*/, 2 /*failed_cycles_tolerance*/, 1 /*min_indications*/, 3 /*max_indications*/); auto app_profile = fb::CreateApplicationProfile( fbb, fb::ApplicationType::Reporting_And_Supervised, true /*is_self_terminating*/, alive_sup); - auto bin_name = fbb.CreateString("my_binary"); auto dep = fbb.CreateString("other_comp"); auto deps_vec = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{dep}); auto arg = fbb.CreateString("--verbose"); auto args_vec = fbb.CreateVector(std::vector<::flatbuffers::Offset<::flatbuffers::String>>{arg}); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); - auto comp_props = fb::CreateComponentProperties(fbb, bin_name, app_profile, deps_vec, args_vec, ready_cond); + auto comp_props = fb::CreateComponentProperties(fbb, app_profile, deps_vec, args_vec, ready_cond); - auto bin_dir = fbb.CreateString("/opt/bin"); + auto exec_path = fbb.CreateString("/opt/bin/my_binary"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, 1.5 /*ready_timeout*/, 2.5 /*shutdown_timeout*/, 0 /*environmental_variables*/, - bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); auto comp_name = fbb.CreateString("TestComponent"); auto comp_desc = fbb.CreateString("A test component"); @@ -223,7 +221,6 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponent) const auto& comp = result->components()[0]; EXPECT_THAT(comp.name, Eq("TestComponent")); EXPECT_THAT(comp.description, Eq("A test component")); - EXPECT_THAT(comp.component_properties.binary_name, Eq("my_binary")); EXPECT_THAT(comp.component_properties.application_profile.application_type, Eq(ApplicationType::ReportingAndSupervised)); EXPECT_THAT(comp.component_properties.application_profile.is_self_terminating, IsTrue()); @@ -242,7 +239,7 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSingleComponent) EXPECT_THAT(comp.component_properties.ready_condition->process_state, Eq(ProcessState::Running)); EXPECT_THAT(comp.deployment_config.ready_timeout_ms, Eq(1500U)); EXPECT_THAT(comp.deployment_config.shutdown_timeout_ms, Eq(2500U)); - EXPECT_THAT(comp.deployment_config.bin_dir, Eq("/opt/bin")); + EXPECT_THAT(comp.deployment_config.executable_path, Eq("/opt/bin/my_binary")); EXPECT_THAT(comp.deployment_config.working_dir, Eq("/tmp")); } @@ -357,14 +354,14 @@ TEST_F(FlatbufferConfigLoaderTest, LoadRestartRecoveryAction) ::flatbuffers::FlatBufferBuilder fbb; auto restart = fb::CreateRestartAction(fbb, 3 /*number_of_attempts*/, 1.5 /*delay_before_restart*/); - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/restart_bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, - bin_dir, + exec_path, work_dir, restart, 0 /*recovery_action*/, @@ -421,13 +418,13 @@ TEST_F(FlatbufferConfigLoaderTest, LoadSandbox) 4096 /*max_memory_usage*/, 80 /*max_cpu_usage*/); - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/sandboxed_bin"); auto work_dir = fbb.CreateString("/tmp"); auto deploy = fb::CreateDeploymentConfig(fbb, 0.5 /*ready_timeout*/, 0.5 /*shutdown_timeout*/, 0 /*environmental_variables*/, - bin_dir, + exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, @@ -465,10 +462,9 @@ TEST_F(FlatbufferConfigLoaderTest, LoadComponentAliveSupervision) fbb, 1.0 /*reporting_cycle*/, 3 /*failed_cycles_tolerance*/, 2 /*min_indications*/, 5 /*max_indications*/); auto app_profile = fb::CreateApplicationProfile( fbb, fb::ApplicationType::Reporting_And_Supervised, false /*is_self_terminating*/, comp_alive_sup); - auto bin_name = fbb.CreateString("supervised_bin"); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); auto comp_props = fb::CreateComponentProperties( - fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); + fbb, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); auto comp = buildDefaultComponent(fbb, "supervised_comp", comp_props); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{comp}); @@ -500,12 +496,12 @@ TEST_F(FlatbufferConfigLoaderTest, LoadEnvironmentalVariables) auto ev2 = fb::CreateEnvironmentalVariable(fbb, k2, v2); auto env_vars = fbb.CreateVector(std::vector<::flatbuffers::Offset>{ev1, ev2}); - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/env_bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, 0.5 /*ready_timeout*/, 0.5 /*shutdown_timeout*/, env_vars, - bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); auto comp = buildDefaultComponent(fbb, "env_comp", buildDefaultComponentProperties(fbb), deploy); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{comp}); @@ -567,9 +563,8 @@ TEST_F(FlatbufferConfigLoaderTest, OptionalReadyConditionAbsent) ::flatbuffers::FlatBufferBuilder fbb; - auto bin_name = fbb.CreateString("no_rc_bin"); auto app_profile = fb::CreateApplicationProfile(fbb, fb::ApplicationType::Native, false); - auto comp_props = fb::CreateComponentProperties(fbb, bin_name, app_profile); + auto comp_props = fb::CreateComponentProperties(fbb, app_profile); auto comp = buildDefaultComponent(fbb, "no_rc_comp", comp_props); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{comp}); diff --git a/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters.cpp b/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters.cpp index f5e76b3bb..9d5270abf 100644 --- a/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters.cpp +++ b/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters.cpp @@ -314,9 +314,7 @@ score::cpp::expected convertComponent ComponentProperties result{}; if (fb_cp != nullptr) { - assert(fb_cp->binary_name() && "ComponentProperties::binary_name must never be nullptr as it is required in the schema"); assert(fb_cp->application_profile() && "ComponentProperties::application_profile must never be nullptr as it is required in the schema"); - result.binary_name = fb_cp->binary_name()->str(); auto app_profile = convertApplicationProfile(fb_cp->application_profile()); if (!app_profile.has_value()) { @@ -400,7 +398,7 @@ score::cpp::expected convertDeploymentCo DeploymentConfig result{}; if (fb_dc != nullptr) { - assert(fb_dc->bin_dir() && "DeploymentConfig::bin_dir must never be nullptr as it is required in the schema"); + assert(fb_dc->executable_path() && "DeploymentConfig::executable_path must never be nullptr as it is required in the schema"); assert(fb_dc->working_dir() && "DeploymentConfig::working_dir must never be nullptr as it is required in the schema"); assert(fb_dc->sandbox() && "DeploymentConfig::sandbox must never be nullptr as it is required in the schema"); auto ready_timeout = requireScalarValue(fb_dc->ready_timeout(), "DeploymentConfig::ready_timeout"); @@ -428,7 +426,7 @@ score::cpp::expected convertDeploymentCo result.ready_timeout_ms = *ready_timeout_ms; result.shutdown_timeout_ms = *shutdown_timeout_ms; result.environmental_variables = convertEnvironmentalVariables(fb_dc->environmental_variables()); - result.bin_dir = fb_dc->bin_dir()->str(); + result.executable_path = fb_dc->executable_path()->str(); result.working_dir = fb_dc->working_dir()->str(); auto ready_recovery = convertRestartAction(fb_dc->ready_recovery_action()); if (!ready_recovery.has_value()) diff --git a/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp b/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp index 4daca97d2..afb37841b 100644 --- a/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp +++ b/score/launch_manager/daemon/src/configuration/details/flatbuffer_type_converters_UT.cpp @@ -716,12 +716,12 @@ TEST_F(ConverterTest, ConvertDeploymentConfigValid) { RecordProperty("Description", "convertDeploymentConfig maps all fields correctly."); ::flatbuffers::FlatBufferBuilder fbb; - auto bin_dir = fbb.CreateString("/opt/bin"); + auto exec_path = fbb.CreateString("/opt/bin/my_app"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); auto deploy = fb::CreateDeploymentConfig( fbb, 1.5 /*ready_timeout*/, 2.5 /*shutdown_timeout*/, 0 /*environmental_variables*/, - bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); fbb.Finish(deploy); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -729,7 +729,7 @@ TEST_F(ConverterTest, ConvertDeploymentConfigValid) ASSERT_THAT(result.has_value(), IsTrue()); EXPECT_THAT(result->ready_timeout_ms, Eq(1500U)); EXPECT_THAT(result->shutdown_timeout_ms, Eq(2500U)); - EXPECT_THAT(result->bin_dir, Eq("/opt/bin")); + EXPECT_THAT(result->executable_path, Eq("/opt/bin/my_app")); EXPECT_THAT(result->working_dir, Eq("/tmp")); EXPECT_THAT(result->ready_recovery_action.has_value(), IsFalse()); EXPECT_THAT(result->recovery_action.has_value(), IsFalse()); @@ -739,10 +739,10 @@ TEST_F(ConverterTest, ConvertDeploymentConfigMissingReadyTimeoutReturnsError) { RecordProperty("Description", "Missing ready_timeout returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); - auto deploy = fb::CreateDeploymentConfig(fbb, ::flatbuffers::nullopt /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + auto deploy = fb::CreateDeploymentConfig(fbb, ::flatbuffers::nullopt /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); fbb.Finish(deploy); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -755,10 +755,10 @@ TEST_F(ConverterTest, ConvertDeploymentConfigMissingShutdownTimeoutReturnsError) { RecordProperty("Description", "Missing shutdown_timeout returns InvalidFormat."); ::flatbuffers::FlatBufferBuilder fbb; - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); - auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, ::flatbuffers::nullopt /*shutdown_timeout*/, 0 /*environmental_variables*/, bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, ::flatbuffers::nullopt /*shutdown_timeout*/, 0 /*environmental_variables*/, exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); fbb.Finish(deploy); const auto* ptr = ::flatbuffers::GetRoot(fbb.GetBufferPointer()); @@ -773,14 +773,13 @@ TEST_F(ConverterTest, ConvertComponentValid) ::flatbuffers::FlatBufferBuilder fbb; auto app_profile = fb::CreateApplicationProfile(fbb, fb::ApplicationType::Native, false /*is_self_terminating*/); - auto bin_name = fbb.CreateString("my_binary"); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); - auto comp_props = fb::CreateComponentProperties(fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); + auto comp_props = fb::CreateComponentProperties(fbb, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); - auto bin_dir = fbb.CreateString("/opt"); + auto exec_path = fbb.CreateString("/opt/my_binary"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); - auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); auto comp_name = fbb.CreateString("TestComp"); auto comp_desc = fbb.CreateString("A test component"); @@ -792,7 +791,6 @@ TEST_F(ConverterTest, ConvertComponentValid) ASSERT_THAT(result.has_value(), IsTrue()); EXPECT_THAT(result->name, Eq("TestComp")); EXPECT_THAT(result->description, Eq("A test component")); - EXPECT_THAT(result->component_properties.binary_name, Eq("my_binary")); EXPECT_THAT(result->deployment_config.ready_timeout_ms, Eq(1000U)); } @@ -803,13 +801,12 @@ TEST_F(ConverterTest, ConvertComponentsValid) auto build_comp = [&](const char* name) { auto app_profile = fb::CreateApplicationProfile(fbb, fb::ApplicationType::Native, false /*is_self_terminating*/); - auto bin_name = fbb.CreateString(name); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); - auto comp_props = fb::CreateComponentProperties(fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); - auto bin_dir = fbb.CreateString("/opt"); + auto comp_props = fb::CreateComponentProperties(fbb, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); + auto exec_path = fbb.CreateString(std::string("/opt/") + name); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); - auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); auto comp_name = fbb.CreateString(name); return fb::CreateComponent(fbb, comp_name, 0 /*description*/, comp_props, deploy); }; @@ -836,13 +833,12 @@ TEST_F(ConverterTest, ConvertComponentsWithInvalidComponentReturnsError) ::flatbuffers::FlatBufferBuilder fbb; auto app_profile = fb::CreateApplicationProfile(fbb, ::flatbuffers::nullopt /*application_type*/, false /*is_self_terminating*/); - auto bin_name = fbb.CreateString("bad_bin"); auto ready_cond = fb::CreateReadyCondition(fbb, fb::ProcessState::Running); - auto comp_props = fb::CreateComponentProperties(fbb, bin_name, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); - auto bin_dir = fbb.CreateString("/opt"); + auto comp_props = fb::CreateComponentProperties(fbb, app_profile, 0 /*depends_on*/, 0 /*process_arguments*/, ready_cond); + auto exec_path = fbb.CreateString("/opt/bad_bin"); auto work_dir = fbb.CreateString("/tmp"); auto sandbox = buildDefaultSandbox(fbb); - auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, bin_dir, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); + auto deploy = fb::CreateDeploymentConfig(fbb, 1.0 /*ready_timeout*/, 1.0 /*shutdown_timeout*/, 0 /*environmental_variables*/, exec_path, work_dir, 0 /*ready_recovery_action*/, 0 /*recovery_action*/, sandbox); auto comp_name = fbb.CreateString("BadComp"); auto comp = fb::CreateComponent(fbb, comp_name, 0 /*description*/, comp_props, deploy); auto comps = fbb.CreateVector(std::vector<::flatbuffers::Offset>{comp}); diff --git a/score/launch_manager/daemon/src/configuration/details/new_lm_flatcfg.fbs b/score/launch_manager/daemon/src/configuration/details/new_lm_flatcfg.fbs index 98e716324..9c109420e 100644 --- a/score/launch_manager/daemon/src/configuration/details/new_lm_flatcfg.fbs +++ b/score/launch_manager/daemon/src/configuration/details/new_lm_flatcfg.fbs @@ -60,8 +60,6 @@ table ReadyCondition { // Defines essential characteristics of a software component. table ComponentProperties { - // Relative path of the executable inside bin_dir. - binary_name:string (required); // required application_profile:ApplicationProfile (required); // required // Names of components that must reach ready state before this component starts. depends_on:[string]; // optional @@ -118,8 +116,8 @@ table DeploymentConfig { shutdown_timeout:double = null; // required // Environment variables passed to the component at startup. environmental_variables:[EnvironmentalVariable]; // optional - // Absolute path to the directory where the component is installed. - bin_dir:string (required); // required + // Absolute path to the executable. + executable_path:string (required); // required // Working directory for the component during execution. working_dir:string (required); // required // Recovery action when the component fails to reach ready state. diff --git a/score/launch_manager/daemon/src/main.cpp b/score/launch_manager/daemon/src/main.cpp index a24dc13f1..67656211a 100644 --- a/score/launch_manager/daemon/src/main.cpp +++ b/score/launch_manager/daemon/src/main.cpp @@ -88,11 +88,24 @@ void reserveFD(int fd) // coverity[autosar_cpp14_a15_3_3_violation:FALSE] Only logging occurs outside the try-catch enclosing main(). int main(int argc, const char* argv[]) { - const char* config_path = "etc/launch_manager_config.bin"; + const char* config_path = "etc/launch_manager_config_gen.bin"; int opt; - while ((opt = getopt(argc, const_cast(argv), "c:")) != -1) { - if (opt == 'c') { - config_path = optarg; + while ((opt = getopt(argc, const_cast(argv), "c:h")) != -1) { + switch (opt) { + case 'c': + config_path = optarg; + break; + case 'h': + std::cout << "Usage: launch_manager [-c ] [-h]\n" + << "\n" + << "Options:\n" + << " -c Path to the flatbuffer config binary.\n" + << " Default: etc/launch_manager_config_gen.bin\n" + << " -h Print this help and exit.\n"; + return EXIT_SUCCESS; + default: + std::cerr << "Usage: launch_manager [-c ] [-h]\n"; + return EXIT_FAILURE; } } // reserve files descriptor osal::IpcCommsSync::sync_fd (fd3) and @@ -140,16 +153,11 @@ int main(int argc, const char* argv[]) if (process_group_manager->initialize(*config_result)) { - LM_LOG_INFO() << "LCM started successfully"; if (runLCMDaemon(*process_group_manager)) { exit_code = EXIT_SUCCESS; } } - else - { - LM_LOG_FATAL() << "LCM startup failed"; - } if (process_group_manager) { diff --git a/score/launch_manager/docs/user_guide/getting_started.rst b/score/launch_manager/docs/user_guide/getting_started.rst new file mode 100644 index 000000000..a684535fb --- /dev/null +++ b/score/launch_manager/docs/user_guide/getting_started.rst @@ -0,0 +1,154 @@ +.. + # ******************************************************************************* + # Copyright (c) 2026 Contributors to the Eclipse Foundation + # + # See the NOTICE file(s) distributed with this work for additional + # information regarding copyright ownership. + # + # This program and the accompanying materials are made available under the + # terms of the Apache License Version 2.0 which is available at + # https://www.apache.org/licenses/LICENSE-2.0 + # + # SPDX-License-Identifier: Apache-2.0 + # ******************************************************************************* + +Getting Started +############### + +This guide walks through creating a minimal Launch Manager configuration and running the +daemon for the first time. + +Prerequisites +************* + +- The ``launch_manager`` binary built and available on your target. +- Python 3 with the ``jsonschema`` package installed (required for config validation). +- The ``flatc`` FlatBuffers compiler available on your host or target. + +Configuration +************* + +The Launch Manager reads its configuration from a FlatBuffers binary file. The usual +workflow is: + +1. Write a human-readable JSON config file. +2. Convert it to a FlatBuffers-compatible JSON using ``lifecycle_config.py``. +3. Compile the FlatBuffers JSON to a binary with ``flatc``. + +Step 1 — Write the JSON config +============================== + +Create a file ``my_config.json``: + +.. code-block:: json + + { + "schema_version": 1, + "components": { + "my_app": { + "description": "My application", + "component_properties": { + "binary_name": "my_app", + "application_profile": { + "application_type": "Native", + "is_self_terminating": false + } + }, + "deployment_config": { + "bin_dir": "/opt/apps/my_app" + } + } + }, + "run_targets": { + "Startup": { + "description": "System started", + "depends_on": ["my_app"], + "recovery_action": { + "switch_run_target": { + "run_target": "fallback_run_target" + } + } + } + }, + "initial_run_target": "Startup", + "fallback_run_target": { + "description": "Safe shutdown", + "transition_timeout": 1.5 + }, + "alive_supervision": { + "evaluation_cycle": 0.5 + } + } + +Step 2 — Generate the FlatBuffers JSON +======================================= + +.. note:: + + When building with Bazel, steps 2 and 3 are handled automatically by the + ``launch_manager_config`` rule (see `Bazel Integration`_). It invokes the correct + versions of ``lifecycle_config.py`` and ``flatc`` as declared in the build graph, + so manual invocation is only needed outside of Bazel. + +.. code-block:: bash + + python3 scripts/config_mapping/lifecycle_config.py \ + my_config.json \ + --schema score/launch_manager/daemon/src/configuration/config_schema/launch_manager.schema.json \ + -o out/ + +This produces ``out/my_config_gen.json``. + +Step 3 — Compile to a FlatBuffers binary +========================================= + +.. code-block:: bash + + flatc -b -o out/ \ + score/launch_manager/daemon/src/configuration/new_lm_flatcfg.fbs \ + out/my_config_gen.json + +This produces ``out/my_config_gen.bin``. + +Step 4 — Run the Launch Manager +================================ + +By default the daemon looks for the config at ``etc/launch_manager_config_gen.bin`` +relative to its working directory. Use ``-c`` to point it at a different path: + +.. code-block:: bash + + launch_manager -c out/my_config_gen.bin + +Command-line Options +******************** + +.. code-block:: text + + Usage: launch_manager [-c ] [-h] + + Options: + -c Path to the flatbuffer config binary. + Default: etc/launch_manager_config_gen.bin + -h Print this help and exit. + +Passing an unknown option prints the usage line and exits with a non-zero exit code. + +Bazel Integration +***************** + +When building with Bazel the ``launch_manager_config`` rule handles steps 2–3 +automatically. It pins the versions of ``lifecycle_config.py`` and ``flatc`` that are +declared in the build graph, ensuring that the schema, the mapping script, and the +compiler are always consistent with each other. The rule writes +``launch_manager_config.bin`` into the declared output directory: + +.. code-block:: python + + load("//:defs.bzl", "launch_manager_config") + + launch_manager_config( + name = "my_config", + config = ":my_config.json", + flatbuffer_out_dir = "etc", + ) diff --git a/scripts/config_mapping/config.bzl b/scripts/config_mapping/config.bzl index dbae347a6..60fc78642 100644 --- a/scripts/config_mapping/config.bzl +++ b/scripts/config_mapping/config.bzl @@ -38,7 +38,7 @@ def _launch_manager_config_impl(ctx): "-o", gen_dir_flatbuffer.path, lm_schema.path, - gen_dir_json.path + "/launch_manager_config.json", + gen_dir_json.path + "/" + config.basename.replace(".json", "_gen.json"), ], ) diff --git a/scripts/config_mapping/integration_tests.py b/scripts/config_mapping/integration_tests.py index 31a250a0b..ed65df790 100644 --- a/scripts/config_mapping/integration_tests.py +++ b/scripts/config_mapping/integration_tests.py @@ -158,7 +158,7 @@ def test_launch_config_mapping(): test_name = "lm_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, compare_files_only=["launch_manager_config.json"]) + run(input_file, test_name, compare_files_only=["lm_config_gen.json"]) def test_empty_launch_config_mapping(): @@ -168,7 +168,7 @@ def test_empty_launch_config_mapping(): test_name = "empty_lm_config_test" input_file = tests_dir / test_name / "input" / "lm_config.json" - run(input_file, test_name, compare_files_only=["launch_manager_config.json"]) + run(input_file, test_name, compare_files_only=["lm_config_gen.json"]) def test_custom_validation_failures(): diff --git a/scripts/config_mapping/lifecycle_config.py b/scripts/config_mapping/lifecycle_config.py index 545291f16..9bbdfc6b8 100644 --- a/scripts/config_mapping/lifecycle_config.py +++ b/scripts/config_mapping/lifecycle_config.py @@ -3,6 +3,7 @@ import argparse from copy import deepcopy import json +import os import sys from typing import Dict, Any @@ -270,7 +271,10 @@ def schema_validation(json_input, schema, config_path=None, schema_path=None): SCHEMA_VALIDATION_FAILURE = 2 CUSTOM_VALIDATION_FAILURE = 3 -OUTPUT_FILENAME = "launch_manager_config.json" +def output_filename(input_path: str) -> str: + """Derive the output filename from the input filename: _gen.json.""" + stem = os.path.splitext(os.path.basename(input_path))[0] + return f"{stem}_gen.json" _WATCHDOG_REQUIRED = ( "device_file_path", @@ -308,11 +312,13 @@ def _map_sandbox(sandbox): return result -def _map_deployment_config(deployment): +def _map_deployment_config(deployment, binary_name=""): + bin_dir = deployment["bin_dir"].rstrip("/") + executable_path = f"{bin_dir}/{binary_name}" if binary_name else bin_dir result = { "ready_timeout": deployment["ready_timeout"], "shutdown_timeout": deployment["shutdown_timeout"], - "bin_dir": deployment["bin_dir"], + "executable_path": executable_path, "working_dir": deployment["working_dir"], "sandbox": _map_sandbox(deployment["sandbox"]), } @@ -355,7 +361,6 @@ def _map_application_profile(profile): def _map_component_properties(props): result = { - "binary_name": props["binary_name"], "application_profile": _map_application_profile(props["application_profile"]), } if (depends_on := props.get("depends_on")) is not None: @@ -397,15 +402,14 @@ def _map_fallback_run_target(fallback): return result -def gen_config(output_dir, config): +def gen_config(output_dir, config, out_filename="launch_manager_config.json"): """ - Generate a single launch_manager_config.json matching new_lm_flatcfg.fbs. + Generate a single JSON file matching new_lm_flatcfg.fbs. Input: output_dir: Directory where the file is written config: Preprocessed configuration with all defaults applied - Output: - A file named "launch_manager_config.json" + out_filename: Name of the output file (default kept for unit tests) """ output = {} @@ -419,7 +423,10 @@ def gen_config(output_dir, config): "component_properties": _map_component_properties( component["component_properties"] ), - "deployment_config": _map_deployment_config(component["deployment_config"]), + "deployment_config": _map_deployment_config( + component["deployment_config"], + component["component_properties"].get("binary_name", ""), + ), } for name, component in config["components"].items() ] @@ -444,7 +451,7 @@ def gen_config(output_dir, config): raise ValueError(f"watchdog config is missing required fields: {missing}") output["watchdog"] = {f: watchdog[f] for f in _WATCHDOG_REQUIRED} - with open(f"{output_dir}/{OUTPUT_FILENAME}", "w") as f: + with open(f"{output_dir}/{out_filename}", "w") as f: json.dump(output, f, indent=4) @@ -502,7 +509,7 @@ def main(): exit(CUSTOM_VALIDATION_FAILURE) try: - gen_config(args.output_dir, preprocessed_config) + gen_config(args.output_dir, preprocessed_config, output_filename(args.filename)) except ValueError as e: print(f"Error during configuration generation: {e}", file=sys.stderr) exit(CUSTOM_VALIDATION_FAILURE) diff --git a/scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/basic_test/expected_output/lm_config_gen.json similarity index 96% rename from scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json rename to scripts/config_mapping/tests/basic_test/expected_output/lm_config_gen.json index 886e85ce5..d36786547 100644 --- a/scripts/config_mapping/tests/basic_test/expected_output/launch_manager_config.json +++ b/scripts/config_mapping/tests/basic_test/expected_output/lm_config_gen.json @@ -5,7 +5,6 @@ "name": "setup_filesystem_sh", "description": "Script to mount partitions at the right directories", "component_properties": { - "binary_name": "bin/setup_filesystem.sh", "application_profile": { "application_type": "Native", "is_self_terminating": true @@ -22,7 +21,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/setup_filesystem.sh", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -65,7 +64,6 @@ "name": "dlt-daemon", "description": "Logging application", "component_properties": { - "binary_name": "dltd", "application_profile": { "application_type": "Native", "is_self_terminating": false @@ -85,7 +83,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/dlt-daemon", + "executable_path": "/opt/apps/dlt-daemon/dltd", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -128,7 +126,6 @@ "name": "someip-daemon", "description": "SOME/IP application", "component_properties": { - "binary_name": "someipd", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": false, @@ -152,7 +149,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/someip", + "executable_path": "/opt/apps/someip/someipd", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -195,7 +192,6 @@ "name": "test_app1", "description": "Simple test application", "component_properties": { - "binary_name": "test_app1", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": false, @@ -222,7 +218,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/test_app1", + "executable_path": "/opt/apps/test_app1/test_app1", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -265,7 +261,6 @@ "name": "state_manager", "description": "Application that manages life cycle of the ECU", "component_properties": { - "binary_name": "sm", "application_profile": { "application_type": "State_Manager", "is_self_terminating": false, @@ -291,7 +286,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/state_manager", + "executable_path": "/opt/apps/state_manager/sm", "working_dir": "/tmp", "sandbox": { "uid": 1000, diff --git a/scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/empty_health_config_test/expected_output/lm_config_gen.json similarity index 96% rename from scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json rename to scripts/config_mapping/tests/empty_health_config_test/expected_output/lm_config_gen.json index 43db9a204..95ff17b87 100644 --- a/scripts/config_mapping/tests/empty_health_config_test/expected_output/launch_manager_config.json +++ b/scripts/config_mapping/tests/empty_health_config_test/expected_output/lm_config_gen.json @@ -5,7 +5,6 @@ "name": "non_supervised_comp", "description": "Non-supervised component", "component_properties": { - "binary_name": "bin/comp", "application_profile": { "application_type": "Native", "is_self_terminating": true @@ -19,7 +18,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/comp", "working_dir": "/tmp", "sandbox": { "uid": 3, diff --git a/scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_config_gen.json similarity index 100% rename from scripts/config_mapping/tests/empty_lm_config_test/expected_output/launch_manager_config.json rename to scripts/config_mapping/tests/empty_lm_config_test/expected_output/lm_config_gen.json diff --git a/scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/health_config_test/expected_output/lm_config_gen.json similarity index 95% rename from scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json rename to scripts/config_mapping/tests/health_config_test/expected_output/lm_config_gen.json index ff57e886b..a19dad0d7 100644 --- a/scripts/config_mapping/tests/health_config_test/expected_output/launch_manager_config.json +++ b/scripts/config_mapping/tests/health_config_test/expected_output/lm_config_gen.json @@ -5,7 +5,6 @@ "name": "non_supervised_comp", "description": "Non-supervised component", "component_properties": { - "binary_name": "bin/comp", "application_profile": { "application_type": "Native", "is_self_terminating": true @@ -19,7 +18,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/comp", "working_dir": "/tmp", "sandbox": { "uid": 3, @@ -42,7 +41,6 @@ "name": "state_manager", "description": "StateManager with min_indications set to 0", "component_properties": { - "binary_name": "sm", "application_profile": { "application_type": "State_Manager", "is_self_terminating": false, @@ -62,7 +60,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/state_manager", + "executable_path": "/opt/apps/state_manager/sm", "working_dir": "/tmp", "sandbox": { "uid": 4, @@ -85,7 +83,6 @@ "name": "reporting_supervised_component", "description": "Component reporting Running state and supervised", "component_properties": { - "binary_name": "bin/comp", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": true, @@ -108,7 +105,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/comp", "working_dir": "/tmp", "sandbox": { "uid": 5, @@ -131,7 +128,6 @@ "name": "reporting_supervised_component_with_no_max_indications", "description": "Component reporting Running state and supervised with max_indications=0", "component_properties": { - "binary_name": "bin/comp", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": true, @@ -154,7 +150,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/comp", "working_dir": "/tmp", "sandbox": { "uid": 5, diff --git a/scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json b/scripts/config_mapping/tests/lm_config_test/expected_output/lm_config_gen.json similarity index 96% rename from scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json rename to scripts/config_mapping/tests/lm_config_test/expected_output/lm_config_gen.json index 623cc95c3..0429b2e61 100644 --- a/scripts/config_mapping/tests/lm_config_test/expected_output/launch_manager_config.json +++ b/scripts/config_mapping/tests/lm_config_test/expected_output/lm_config_gen.json @@ -5,7 +5,6 @@ "name": "test_app2", "description": "Another simple test application", "component_properties": { - "binary_name": "test_app2", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": false, @@ -29,7 +28,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/test_app2", + "executable_path": "/opt/apps/test_app2/test_app2", "working_dir": "/tmp", "sandbox": { "uid": 2000, @@ -75,7 +74,6 @@ "name": "setup_filesystem_sh", "description": "Script to mount partitions at the right directories", "component_properties": { - "binary_name": "bin/setup_filesystem.sh", "application_profile": { "application_type": "Native", "is_self_terminating": true @@ -94,7 +92,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/scripts", + "executable_path": "/opt/scripts/bin/setup_filesystem.sh", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -137,7 +135,6 @@ "name": "dlt-daemon", "description": "Logging application", "component_properties": { - "binary_name": "dltd", "application_profile": { "application_type": "Native", "is_self_terminating": false @@ -157,7 +154,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/dlt-daemon", + "executable_path": "/opt/apps/dlt-daemon/dltd", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -200,7 +197,6 @@ "name": "someip-daemon", "description": "SOME/IP application", "component_properties": { - "binary_name": "someipd", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": false, @@ -224,7 +220,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/someip", + "executable_path": "/opt/apps/someip/someipd", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -267,7 +263,6 @@ "name": "test_app1", "description": "Simple test application", "component_properties": { - "binary_name": "test_app1", "application_profile": { "application_type": "Reporting_And_Supervised", "is_self_terminating": false, @@ -294,7 +289,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/test_app1", + "executable_path": "/opt/apps/test_app1/test_app1", "working_dir": "/tmp", "sandbox": { "uid": 1000, @@ -337,7 +332,6 @@ "name": "state_manager", "description": "Application that manages life cycle of the ECU", "component_properties": { - "binary_name": "sm", "application_profile": { "application_type": "State_Manager", "is_self_terminating": false, @@ -363,7 +357,7 @@ "deployment_config": { "ready_timeout": 0.5, "shutdown_timeout": 0.5, - "bin_dir": "/opt/apps/state_manager", + "executable_path": "/opt/apps/state_manager/sm", "working_dir": "/tmp", "sandbox": { "uid": 1000, diff --git a/scripts/config_mapping/unit_tests.py b/scripts/config_mapping/unit_tests.py index e2bdfa80d..53368f847 100644 --- a/scripts/config_mapping/unit_tests.py +++ b/scripts/config_mapping/unit_tests.py @@ -283,7 +283,6 @@ def test_gen_config_component_fields(): comp = next(c for c in output["components"] if c["name"] == "app_a") assert comp["description"] == "First app" - assert comp["component_properties"]["binary_name"] == "app_a_bin" assert comp["component_properties"]["application_profile"]["application_type"] == "Reporting_And_Supervised" assert comp["component_properties"]["application_profile"]["is_self_terminating"] is False assert comp["component_properties"]["application_profile"]["alive_supervision"]["reporting_cycle"] == 0.5 @@ -292,7 +291,7 @@ def test_gen_config_component_fields(): assert comp["deployment_config"]["ready_timeout"] == 0.5 assert comp["deployment_config"]["shutdown_timeout"] == 0.5 - assert comp["deployment_config"]["bin_dir"] == "/opt/apps" + assert comp["deployment_config"]["executable_path"] == "/opt/apps/app_a_bin" assert "sandbox" in comp["deployment_config"] assert comp["deployment_config"]["sandbox"]["uid"] == 1000 assert comp["deployment_config"]["sandbox"]["scheduling_policy"] == "OTHER" diff --git a/tests/integration/complex_monitoring/complex_monitoring.py b/tests/integration/complex_monitoring/complex_monitoring.py index 641f8b1d6..8aa345759 100644 --- a/tests/integration/complex_monitoring/complex_monitoring.py +++ b/tests/integration/complex_monitoring/complex_monitoring.py @@ -35,7 +35,7 @@ def test_complex_monitoring(target, setup_test, assert_test_results, remote_test run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "complex_monitoring_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=4.0, diff --git a/tests/integration/crash_on_startup/crash_on_startup.py b/tests/integration/crash_on_startup/crash_on_startup.py index d4e6a8cb1..715ef7d2e 100644 --- a/tests/integration/crash_on_startup/crash_on_startup.py +++ b/tests/integration/crash_on_startup/crash_on_startup.py @@ -35,7 +35,7 @@ def test_crash_on_startup(target, setup_test, assert_test_results, remote_test_d run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "crash_on_startup_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=6.0, diff --git a/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py b/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py index ba8278f9d..782803b80 100644 --- a/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py +++ b/tests/integration/incorrect_config_non_reporting/test_incorrect_config_non_reporting.py @@ -33,7 +33,7 @@ def test_incorrect_config_non_reporting( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "non_reporting_config_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, diff --git a/tests/integration/process_crash_monitoring/process_crash_monitoring.py b/tests/integration/process_crash_monitoring/process_crash_monitoring.py index 654d687c6..5196d148a 100644 --- a/tests/integration/process_crash_monitoring/process_crash_monitoring.py +++ b/tests/integration/process_crash_monitoring/process_crash_monitoring.py @@ -34,7 +34,7 @@ def test_process_crash_monitoring( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "process_crash_monitoring_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=10.0, diff --git a/tests/integration/process_launch_args/process_launch_args.py b/tests/integration/process_launch_args/process_launch_args.py index 8227458bb..7013b18da 100644 --- a/tests/integration/process_launch_args/process_launch_args.py +++ b/tests/integration/process_launch_args/process_launch_args.py @@ -37,7 +37,7 @@ def test_process_launch_args(target, setup_test, assert_test_results, remote_tes run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "process_launch_args_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, diff --git a/tests/integration/smoke/smoke.py b/tests/integration/smoke/smoke.py index 92bb0b01c..71f5bcbc8 100644 --- a/tests/integration/smoke/smoke.py +++ b/tests/integration/smoke/smoke.py @@ -32,7 +32,7 @@ def test_smoke(target, setup_test, assert_test_results, remote_test_dir): run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "lifecycle_smoketest_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=3.0, diff --git a/tests/integration/switch_run_target/switch_run_target.py b/tests/integration/switch_run_target/switch_run_target.py index f658f4ec3..1b45a65e9 100644 --- a/tests/integration/switch_run_target/switch_run_target.py +++ b/tests/integration/switch_run_target/switch_run_target.py @@ -37,7 +37,7 @@ def test_switch_run_target(target, setup_test, assert_test_results, remote_test_ run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "launch_manager_config.bin")], + args=["-c", str(remote_test_dir / "etc" / "switch_run_target_gen.bin")], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=2.0, From a5b69ecce760f0f99e50a7899eee09ae828f61a2 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Fri, 19 Jun 2026 16:11:20 +0200 Subject: [PATCH 5/7] Fix CI issues --- examples/demo_verification/test_examples.py | 6 +++- .../launch_manager/docs/user_guide/index.rst | 1 + scripts/config_mapping/lifecycle_config.py | 2 ++ scripts/config_mapping/unit_tests.py | 34 ++++++++++++++----- .../process_complex_rep_failure.py | 5 ++- .../process_simple_rep_failure.py | 5 ++- 6 files changed, 42 insertions(+), 11 deletions(-) diff --git a/examples/demo_verification/test_examples.py b/examples/demo_verification/test_examples.py index 73f4a7dee..bf55721d5 100644 --- a/examples/demo_verification/test_examples.py +++ b/examples/demo_verification/test_examples.py @@ -71,7 +71,11 @@ def test_examples(target, setup_test, remote_test_dir): lmcontrol_path = str(remote_test_dir / "lmcontrol") _step("Starting launch manager (Startup)") - lm_proc = target.execute_async(lm_path, args=["-c", "etc/lifecycle_demo_test_gen.bin"], cwd=str(remote_test_dir)) + lm_proc = target.execute_async( + lm_path, + args=["-c", "etc/lifecycle_demo_test_gen.bin"], + cwd=str(remote_test_dir), + ) time.sleep(1.0) assert lm_proc.is_running(), "Launch manager exited unexpectedly during Startup" diff --git a/score/launch_manager/docs/user_guide/index.rst b/score/launch_manager/docs/user_guide/index.rst index 7d0e5eeb3..b236ef857 100644 --- a/score/launch_manager/docs/user_guide/index.rst +++ b/score/launch_manager/docs/user_guide/index.rst @@ -17,6 +17,7 @@ User Guide .. toctree:: + getting_started.rst concepts.rst ready_state.rst configuration.rst diff --git a/scripts/config_mapping/lifecycle_config.py b/scripts/config_mapping/lifecycle_config.py index 9bbdfc6b8..ad498487a 100644 --- a/scripts/config_mapping/lifecycle_config.py +++ b/scripts/config_mapping/lifecycle_config.py @@ -271,11 +271,13 @@ def schema_validation(json_input, schema, config_path=None, schema_path=None): SCHEMA_VALIDATION_FAILURE = 2 CUSTOM_VALIDATION_FAILURE = 3 + def output_filename(input_path: str) -> str: """Derive the output filename from the input filename: _gen.json.""" stem = os.path.splitext(os.path.basename(input_path))[0] return f"{stem}_gen.json" + _WATCHDOG_REQUIRED = ( "device_file_path", "max_timeout", diff --git a/scripts/config_mapping/unit_tests.py b/scripts/config_mapping/unit_tests.py index 53368f847..d74c22d62 100644 --- a/scripts/config_mapping/unit_tests.py +++ b/scripts/config_mapping/unit_tests.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 -from scripts.config_mapping.lifecycle_config import preprocess_defaults, gen_config, score_defaults +from scripts.config_mapping.lifecycle_config import ( + preprocess_defaults, + gen_config, + score_defaults, +) import json import os import tempfile @@ -219,9 +223,9 @@ def _make_preprocessed_config(): config = preprocess_defaults(score_defaults, input_config) config["schema_version"] = input_config["schema_version"] config["initial_run_target"] = input_config["initial_run_target"] - config["fallback_run_target"] = preprocess_defaults( - score_defaults, input_config - )["fallback_run_target"] + config["fallback_run_target"] = preprocess_defaults(score_defaults, input_config)[ + "fallback_run_target" + ] return config @@ -283,9 +287,20 @@ def test_gen_config_component_fields(): comp = next(c for c in output["components"] if c["name"] == "app_a") assert comp["description"] == "First app" - assert comp["component_properties"]["application_profile"]["application_type"] == "Reporting_And_Supervised" - assert comp["component_properties"]["application_profile"]["is_self_terminating"] is False - assert comp["component_properties"]["application_profile"]["alive_supervision"]["reporting_cycle"] == 0.5 + assert ( + comp["component_properties"]["application_profile"]["application_type"] + == "Reporting_And_Supervised" + ) + assert ( + comp["component_properties"]["application_profile"]["is_self_terminating"] + is False + ) + assert ( + comp["component_properties"]["application_profile"]["alive_supervision"][ + "reporting_cycle" + ] + == 0.5 + ) assert comp["component_properties"]["process_arguments"] == ["--flag"] assert comp["component_properties"]["ready_condition"]["process_state"] == "Running" @@ -370,7 +385,10 @@ def test_gen_config_native_app_no_alive_supervision(): output = _run_gen_config(config) native_comp = next(c for c in output["components"] if c["name"] == "app_b") - assert "alive_supervision" not in native_comp["component_properties"]["application_profile"] + assert ( + "alive_supervision" + not in native_comp["component_properties"]["application_profile"] + ) def test_gen_config_depends_on_preserved(): diff --git a/tests/integration/process_complex_rep_failure/process_complex_rep_failure.py b/tests/integration/process_complex_rep_failure/process_complex_rep_failure.py index 014a2bf08..e77859215 100644 --- a/tests/integration/process_complex_rep_failure/process_complex_rep_failure.py +++ b/tests/integration/process_complex_rep_failure/process_complex_rep_failure.py @@ -44,7 +44,10 @@ def test_recovery_action_complex_rep_failure( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "process_complex_rep_failure_gen.bin")], + args=[ + "-c", + str(remote_test_dir / "etc" / "process_complex_rep_failure_gen.bin"), + ], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=10.0, diff --git a/tests/integration/process_simple_rep_failure/process_simple_rep_failure.py b/tests/integration/process_simple_rep_failure/process_simple_rep_failure.py index 72e64ca8e..b5637b766 100644 --- a/tests/integration/process_simple_rep_failure/process_simple_rep_failure.py +++ b/tests/integration/process_simple_rep_failure/process_simple_rep_failure.py @@ -44,7 +44,10 @@ def test_recovery_action_simple_rep_failure( run_until_file_deployed( target=target, binary_path=str(remote_test_dir / "launch_manager"), - args=["-c", str(remote_test_dir / "etc" / "process_simple_rep_failure_gen.bin")], + args=[ + "-c", + str(remote_test_dir / "etc" / "process_simple_rep_failure_gen.bin"), + ], file_path=remote_test_dir.parent / "test_end", cwd=str(remote_test_dir), timeout_s=10.0, From 3276a843ed155eb50ac328eb4178836fae572739 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Tue, 23 Jun 2026 12:10:08 +0200 Subject: [PATCH 6/7] Fix some findings --- .../docs/user_guide/getting_started.rst | 134 +++-------- .../details/daemon/SwClusterHandler.hpp | 16 +- .../details/factory/FlatCfgFactory.cpp | 35 ++- .../details/factory/FlatCfgFactory.hpp | 9 +- .../details/factory/MachineConfigFactory.cpp | 6 +- .../details/factory/MachineConfigFactory.hpp | 7 +- .../details/factory/StaticConfig.hpp | 3 + .../configuration/configuration_adapter.cpp | 35 +-- .../configuration/configuration_adapter.hpp | 4 +- .../configuration_adapter_UT.cpp | 221 ++++++++++++++++++ .../details/flatbuffer_type_converters.cpp | 5 + 11 files changed, 327 insertions(+), 148 deletions(-) diff --git a/score/launch_manager/docs/user_guide/getting_started.rst b/score/launch_manager/docs/user_guide/getting_started.rst index a684535fb..f8b89e1fd 100644 --- a/score/launch_manager/docs/user_guide/getting_started.rst +++ b/score/launch_manager/docs/user_guide/getting_started.rst @@ -18,110 +18,51 @@ Getting Started This guide walks through creating a minimal Launch Manager configuration and running the daemon for the first time. -Prerequisites +Configuration ************* -- The ``launch_manager`` binary built and available on your target. -- Python 3 with the ``jsonschema`` package installed (required for config validation). -- The ``flatc`` FlatBuffers compiler available on your host or target. +The Launch Manager reads its configuration from a FlatBuffers binary file. When building +with Bazel, the ``launch_manager_config`` rule handles the conversion from a human-readable +JSON file to the binary format automatically. -Configuration -************* +Bazel Build Rule +================ -The Launch Manager reads its configuration from a FlatBuffers binary file. The usual -workflow is: - -1. Write a human-readable JSON config file. -2. Convert it to a FlatBuffers-compatible JSON using ``lifecycle_config.py``. -3. Compile the FlatBuffers JSON to a binary with ``flatc``. - -Step 1 — Write the JSON config -============================== - -Create a file ``my_config.json``: - -.. code-block:: json - - { - "schema_version": 1, - "components": { - "my_app": { - "description": "My application", - "component_properties": { - "binary_name": "my_app", - "application_profile": { - "application_type": "Native", - "is_self_terminating": false - } - }, - "deployment_config": { - "bin_dir": "/opt/apps/my_app" - } - } - }, - "run_targets": { - "Startup": { - "description": "System started", - "depends_on": ["my_app"], - "recovery_action": { - "switch_run_target": { - "run_target": "fallback_run_target" - } - } - } - }, - "initial_run_target": "Startup", - "fallback_run_target": { - "description": "Safe shutdown", - "transition_timeout": 1.5 - }, - "alive_supervision": { - "evaluation_cycle": 0.5 - } - } - -Step 2 — Generate the FlatBuffers JSON -======================================= - -.. note:: - - When building with Bazel, steps 2 and 3 are handled automatically by the - ``launch_manager_config`` rule (see `Bazel Integration`_). It invokes the correct - versions of ``lifecycle_config.py`` and ``flatc`` as declared in the build graph, - so manual invocation is only needed outside of Bazel. +Add a ``launch_manager_config`` target to your ``BUILD`` file: -.. code-block:: bash +.. code-block:: starlark + + load("//:defs.bzl", "launch_manager_config") - python3 scripts/config_mapping/lifecycle_config.py \ - my_config.json \ - --schema score/launch_manager/daemon/src/configuration/config_schema/launch_manager.schema.json \ - -o out/ + launch_manager_config( + name = "my_config", + config = ":my_config.json", + flatbuffer_out_dir = "etc", + ) -This produces ``out/my_config_gen.json``. +===================== -Step 3 — Compile to a FlatBuffers binary -========================================= +Create a JSON configuration file that describes the components to launch, the run targets, +and the alive supervision settings. -.. code-block:: bash +.. dropdown:: Example configuration (lifecycle_demo_test.json) - flatc -b -o out/ \ - score/launch_manager/daemon/src/configuration/new_lm_flatcfg.fbs \ - out/my_config_gen.json + .. literalinclude:: ../../../../examples/demo_verification/lifecycle_demo_test.json + :language: json -This produces ``out/my_config_gen.bin``. +For a full description of all available fields see :doc:`configuration`. -Step 4 — Run the Launch Manager -================================ +Running the Launch Manager +************************** -By default the daemon looks for the config at ``etc/launch_manager_config_gen.bin`` -relative to its working directory. Use ``-c`` to point it at a different path: +Start the daemon by pointing it at the generated FlatBuffers binary with the ``-c`` option: .. code-block:: bash - launch_manager -c out/my_config_gen.bin + launch_manager -c etc/my_config_gen.bin Command-line Options -******************** +==================== .. code-block:: text @@ -132,23 +73,4 @@ Command-line Options Default: etc/launch_manager_config_gen.bin -h Print this help and exit. -Passing an unknown option prints the usage line and exits with a non-zero exit code. - -Bazel Integration -***************** - -When building with Bazel the ``launch_manager_config`` rule handles steps 2–3 -automatically. It pins the versions of ``lifecycle_config.py`` and ``flatc`` that are -declared in the build graph, ensuring that the schema, the mapping script, and the -compiler are always consistent with each other. The rule writes -``launch_manager_config.bin`` into the declared output directory: - -.. code-block:: python - - load("//:defs.bzl", "launch_manager_config") - - launch_manager_config( - name = "my_config", - config = ":my_config.json", - flatbuffer_out_dir = "etc", - ) +Passing an unknown option prints the usage line and exits with a non-zero exit code. \ No newline at end of file diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp index 2812d6079..648eef8e0 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/daemon/SwClusterHandler.hpp @@ -53,6 +53,8 @@ namespace daemon /// @brief Software Cluster Handler wraps the full PHM Supervision and Recovery Notification functionality for one /// Software Cluster. +/// @details This class requests construction of all required objects to do the Supervisions and Recovery Notifications +/// for a given Software Cluster. It also provides an abstracted interface to trigger the cyclic evaluation. class SwClusterHandler { public: @@ -79,20 +81,32 @@ class SwClusterHandler SwClusterHandler& operator=(SwClusterHandler&&) = delete; /// @brief Construct required worker objects from the unified Config + /// @param [in] config The parsed launch manager configuration + /// @param [in] f_recoveryClient_r Interface to the launch manager for recovery + /// @param [in] f_processStateReader_r Process state reader object for PHM daemon + /// @param [in] f_bufferConfig_r Configuration settings for constructing workers + /// @return true on success, false on failure bool constructWorkers( const score::mw::launch_manager::configuration::Config& config, std::shared_ptr f_recoveryClient_r, ifexm::ProcessStateReader& f_processStateReader_r, const factory::MachineConfigFactory::SupervisionBufferConfig& f_bufferConfig_r) noexcept(false); - /// @brief Perform cyclic execution + /// @brief Perform cyclic execution required for supervision of the Software Cluster + /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void performCyclicTriggers(const timers::NanoSecondType f_syncTimestamp); /// @brief Check whether any alive supervision failed to enqueue a recovery request + /// @return True if any alive supervision recovery request has failed bool hasAnyRecoveryEnqueueFailed() const noexcept; private: + /// @brief Check all interfaces for new data + /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void checkInterfaceForNewData(const timers::NanoSecondType f_syncTimestamp); + + /// @brief Evaluate all supervisions + /// @param [in] f_syncTimestamp Timestamp for cyclic synchronization void evaluateSupervisions(const timers::NanoSecondType f_syncTimestamp); /// @brief Logger diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp index 4c1952b67..94738111e 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp @@ -13,6 +13,7 @@ #include "score/mw/launch_manager/alive_monitor/details/factory/FlatCfgFactory.hpp" +#include #include #include @@ -60,6 +61,16 @@ FlatCfgFactory::FlatCfgFactory(const factory::MachineConfigFactory::SupervisionB bool FlatCfgFactory::init(const score::mw::launch_manager::configuration::Config& config) { config_ = &config; + + supervised_components_.clear(); + for (const auto& comp : config_->components()) + { + if (isSupervisedType(comp.component_properties.application_profile.application_type)) + { + supervised_components_.push_back(&comp); + } + } + return true; } @@ -70,22 +81,13 @@ bool FlatCfgFactory::createProcessStates(std::vector& f_pro try { - supervised_components_.clear(); - for (const auto& comp : config_->components()) - { - if (isSupervisedType(comp.component_properties.application_profile.application_type)) - { - supervised_components_.push_back(&comp); - } - } - f_processStates_r.reserve(supervised_components_.size()); for (const auto* comp : supervised_components_) { ifexm::ProcessCfg processCfg{}; processCfg.processShortName = std::string_view(comp->name); - const auto processIdResult_p{getProcessId(comp->name)}; + const auto processIdResult_p{getProcessId(comp)}; processCfg.processId = *processIdResult_p; f_processStates_r.emplace_back(processCfg); @@ -236,7 +238,7 @@ bool FlatCfgFactory::createSupervisionCheckpoints(std::vectorname + "_checkpoint"; - const uint32_t checkpointId = 1U; + const uint32_t checkpointId = StaticConfig::k_DefaultCheckpointId; const ifexm::ProcessState* process_p{&f_processStates_r.at(idx)}; f_checkpoints_r.emplace_back(checkpointCfgName.c_str(), checkpointId, process_p); @@ -284,10 +286,7 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ { const auto* comp = supervised_components_[idx]; const auto& alive_sup = comp->component_properties.application_profile.alive_supervision; - if (!alive_sup.has_value()) - { - continue; - } + assert(alive_sup.has_value() && "Supervised component must have alive_supervision configured"); alive_cfg_names_.emplace_back(comp->name + "_alive_supervision"); saf::timers::NanoSecondType aliveReferenceCycleCfg{ @@ -342,10 +341,10 @@ bool FlatCfgFactory::createAliveSupervisions(std::vector& f_ return isSuccess; } -std::optional FlatCfgFactory::getProcessId(const std::string& f_processPath_r) noexcept( - true) +std::optional FlatCfgFactory::getProcessId( + const score::mw::launch_manager::configuration::ComponentConfig* comp) noexcept(true) { - return score::lcm::IdentifierHash{f_processPath_r}.data(); + return score::lcm::IdentifierHash{comp->name}.data(); } } // namespace factory diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp index e58d8f82e..9c8b64aaa 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.hpp @@ -98,10 +98,11 @@ class FlatCfgFactory : public IPhmFactory private: - /// @brief Get process id based on ASR path of process - /// @param[in] f_processPath_r ASR path of process - /// @return process id or nullopt in case of an error - std::optional getProcessId(const std::string& f_processPath_r) noexcept(true); + /// @brief Get process id from a component configuration + /// @param[in] comp Pointer to the component configuration + /// @return process id or nullopt in case of an error + std::optional getProcessId( + const score::mw::launch_manager::configuration::ComponentConfig* comp) noexcept(true); /// @brief Create IPC Channel with uid-based access permission bool initIpcServerWithUidBasedAccess(ifappl::CheckpointIpcServer& f_ipcServer_r, diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp index a01dd2445..acd5ffbf5 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.cpp @@ -39,10 +39,8 @@ MachineConfigFactory::MachineConfigFactory() noexcept(true) : watchdog::IDeviceC bool MachineConfigFactory::init(const score::mw::launch_manager::configuration::Config& config) noexcept(false) { const auto& alive_sup = config.aliveSupervision(); - if (alive_sup.evaluation_cycle_ms != 0U) - { - cycleTimeNs = timers::TimeConversion::convertMilliSecToNanoSec(static_cast(alive_sup.evaluation_cycle_ms)); - } + assert(alive_sup.evaluation_cycle_ms != 0U && "evaluation_cycle_ms must not be zero"); + cycleTimeNs = timers::TimeConversion::convertMilliSecToNanoSec(static_cast(alive_sup.evaluation_cycle_ms)); const auto& wd_opt = config.watchdog(); if (wd_opt.has_value()) diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp index 21c0384dd..ca2f357a2 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/MachineConfigFactory.hpp @@ -38,10 +38,12 @@ namespace factory { /// @brief Factory for loading the HM Machine Configuration from the unified launch_manager_config.bin +/// @details Provides methods to retrieve the settings from the HM Machine configuration if a configuration is +/// provided. If no configuration is provided, the default values are returned. class MachineConfigFactory : public watchdog::IDeviceConfigFactory { public: - /// @brief Holds different buffer sizes that may be configured in the HM Machine Config + /// @brief Holds buffer sizes for supervision objects (currently using compile-time defaults) struct SupervisionBufferConfig { /// @brief Configured buffer size for alive supervisions @@ -72,9 +74,11 @@ class MachineConfigFactory : public watchdog::IDeviceConfigFactory std::optional getDeviceConfigurations() const override; /// @brief Returns the configured hm daemon cycle time in nanoseconds + /// @return Configured cycle time or default cycle time if not configured timers::NanoSecondType getCycleTimeInNs() const noexcept(true); /// @brief Returns the configured buffer sizes for supervisions + /// @return Configured buffer sizes or default values if not configured const SupervisionBufferConfig& getSupervisionBufferConfig() const noexcept(true); private: @@ -82,6 +86,7 @@ class MachineConfigFactory : public watchdog::IDeviceConfigFactory void logConfiguration() noexcept(true); /// @brief Configured watchdog devices + /// By default, no watchdog device is configured watchdog::IDeviceConfigFactory::DeviceConfigurations watchdogConfigs{}; /// @brief Configured HM Daemon cycle time diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/StaticConfig.hpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/StaticConfig.hpp index 74e4acfb4..42b7a9e74 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/StaticConfig.hpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/StaticConfig.hpp @@ -40,6 +40,9 @@ class StaticConfig /// Default buffer size of a Monitor (shared memory) static constexpr uint16_t k_DefaultMonitorBufferElements{ifappl::k_maxCheckpointBufferElements}; + /// @brief Default checkpoint ID used for alive supervision + static constexpr uint32_t k_DefaultCheckpointId{1U}; + /// @brief By default hm daemon shutdown is disabled static constexpr bool k_hmDaemonDefaultShutdownEnabled{false}; /// @brief By default, 10ms cycle time is used diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.cpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.cpp index 49738e399..43e1151c2 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.cpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.cpp @@ -67,7 +67,10 @@ void ConfigurationAdapter::deinitialize() { } } -OsProcess ConfigurationAdapter::buildOsProcess(const ComponentConfig& comp, uint32_t process_index) const { +OsProcess ConfigurationAdapter::buildOsProcess( + const ComponentConfig& comp, + uint32_t process_index, + const std::map& component_by_name) const { OsProcess os_process{}; os_process.process_id_ = IdentifierHash{comp.name}; os_process.process_number_ = process_index; @@ -139,12 +142,15 @@ OsProcess ConfigurationAdapter::buildOsProcess(const ComponentConfig& comp, uint for (const auto& dep_name : props.depends_on) { Dependency dep{}; - if (props.ready_condition.has_value()) { - dep.process_state_ = (props.ready_condition->process_state == ProcessState::Running) - ? score::lcm::ProcessState::kRunning - : score::lcm::ProcessState::kTerminated; - } else { - dep.process_state_ = score::lcm::ProcessState::kRunning; + dep.process_state_ = score::lcm::ProcessState::kRunning; + auto dep_it = component_by_name.find(dep_name); + if (dep_it != component_by_name.end()) { + const auto& dep_props = dep_it->second->component_properties; + if (dep_props.ready_condition.has_value()) { + dep.process_state_ = (dep_props.ready_condition->process_state == ProcessState::Running) + ? score::lcm::ProcessState::kRunning + : score::lcm::ProcessState::kTerminated; + } } dep.target_process_id_ = IdentifierHash{dep_name}; os_process.dependencies_.push_back(dep); @@ -217,11 +223,9 @@ std::vector ConfigurationAdapter::buildProcessGroupStates( const auto& fallback = config.fallbackRunTarget(); ProcessGroupState fallback_state; fallback_state.name_ = IdentifierHash{"MainPG/fallback_run_target"}; - for (const auto& comp_name : fallback.depends_on) { - auto it = component_to_process_index.find(comp_name); - if (it != component_to_process_index.end()) { - fallback_state.process_indexes_.push_back(it->second); - } + std::set visited; + for (const auto& dep_name : fallback.depends_on) { + resolve_depends(dep_name, fallback_state.process_indexes_, visited); } states.push_back(std::move(fallback_state)); } @@ -260,11 +264,16 @@ bool ConfigurationAdapter::buildFromConfig(const Config& config) { } pg.recovery_state_ = recovery_state; + std::map component_by_name; + for (const auto& comp : config.components()) { + component_by_name[comp.name] = ∁ + } + std::map component_to_process_index; uint32_t process_index = 0; for (const auto& comp : config.components()) { component_to_process_index[comp.name] = process_index; - pg.processes_.push_back(buildOsProcess(comp, process_index)); + pg.processes_.push_back(buildOsProcess(comp, process_index, component_by_name)); ++process_index; } diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp index b44a93beb..06da7e935 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter.hpp @@ -100,7 +100,9 @@ class ConfigurationAdapter final { private: bool buildFromConfig(const Config& config); - OsProcess buildOsProcess(const ComponentConfig& comp, uint32_t process_index) const; + OsProcess buildOsProcess(const ComponentConfig& comp, + uint32_t process_index, + const std::map& component_by_name) const; std::vector buildProcessGroupStates( const Config& config, const std::map& component_to_process_index) const; diff --git a/score/launch_manager/src/daemon/src/configuration/configuration_adapter_UT.cpp b/score/launch_manager/src/daemon/src/configuration/configuration_adapter_UT.cpp index 960093a5a..06555b0aa 100644 --- a/score/launch_manager/src/daemon/src/configuration/configuration_adapter_UT.cpp +++ b/score/launch_manager/src/daemon/src/configuration/configuration_adapter_UT.cpp @@ -334,5 +334,226 @@ TEST_F(ConfigurationAdapterTest, OffStateReturnsProcessIndexesListEmpty) EXPECT_TRUE((**result).empty()); } +TEST(ConfigurationAdapterReadyConditionTest, DependencyUsesTargetComponentReadyCondition) +{ + RecordProperty("Description", + "The dependency process_state is derived from the target component's ready_condition, not the source's."); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "explorative-testing"); + + ComponentConfig comp_a; + comp_a.name = "comp_a"; + comp_a.component_properties.application_profile.application_type = ApplicationType::Native; + comp_a.component_properties.application_profile.is_self_terminating = true; + comp_a.component_properties.ready_condition = ReadyCondition{ProcessState::Terminated}; + comp_a.deployment_config.executable_path = "/opt/comp_a"; + comp_a.deployment_config.working_dir = "/tmp"; + comp_a.deployment_config.sandbox.uid = 0; + comp_a.deployment_config.sandbox.gid = 0; + comp_a.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_a.deployment_config.sandbox.scheduling_priority = 0; + + ComponentConfig comp_b; + comp_b.name = "comp_b"; + comp_b.component_properties.application_profile.application_type = ApplicationType::Native; + comp_b.component_properties.application_profile.is_self_terminating = false; + comp_b.component_properties.ready_condition = ReadyCondition{ProcessState::Running}; + comp_b.component_properties.depends_on = {"comp_a"}; + comp_b.deployment_config.executable_path = "/opt/comp_b"; + comp_b.deployment_config.working_dir = "/tmp"; + comp_b.deployment_config.sandbox.uid = 0; + comp_b.deployment_config.sandbox.gid = 0; + comp_b.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_b.deployment_config.sandbox.scheduling_priority = 0; + + std::vector components; + components.push_back(std::move(comp_a)); + components.push_back(std::move(comp_b)); + + RunTargetConfig startup; + startup.name = "Startup"; + startup.depends_on = {"comp_b"}; + startup.transition_timeout_ms = 5000; + startup.recovery_action.run_target = "fallback_run_target"; + + std::vector run_targets; + run_targets.push_back(std::move(startup)); + + FallbackRunTargetConfig fallback; + fallback.transition_timeout_ms = 1500; + AliveSupervisionConfig alive; + alive.evaluation_cycle_ms = 500; + + auto config = ConfigBuilder{} + .setComponents(std::move(components)) + .setRunTargets(std::move(run_targets)) + .setInitialRunTarget("Startup") + .setFallbackRunTarget(std::move(fallback)) + .setAliveSupervision(alive) + .build(); + + ConfigurationAdapter adapter; + adapter.initialize(config); + + IdentifierHash pg_name{"MainPG"}; + auto result = adapter.getOsProcessDependencies(pg_name, 1U); + ASSERT_TRUE(result.has_value()); + const auto* deps = *result; + ASSERT_THAT(deps->size(), Eq(1U)); + EXPECT_THAT((*deps)[0].target_process_id_, Eq(IdentifierHash{"comp_a"})); + EXPECT_THAT((*deps)[0].process_state_, Eq(score::lcm::ProcessState::kTerminated)) + << "Dependency should use comp_a's ready_condition (Terminated), not comp_b's (Running)"; + + adapter.deinitialize(); +} + +TEST(ConfigurationAdapterReadyConditionTest, DependencyDefaultsToRunningWhenTargetHasNoReadyCondition) +{ + RecordProperty("Description", + "When the dependency target has no ready_condition, the dependency defaults to Running."); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "explorative-testing"); + + ComponentConfig comp_a; + comp_a.name = "comp_a"; + comp_a.component_properties.application_profile.application_type = ApplicationType::Native; + comp_a.component_properties.application_profile.is_self_terminating = false; + comp_a.deployment_config.executable_path = "/opt/comp_a"; + comp_a.deployment_config.working_dir = "/tmp"; + comp_a.deployment_config.sandbox.uid = 0; + comp_a.deployment_config.sandbox.gid = 0; + comp_a.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_a.deployment_config.sandbox.scheduling_priority = 0; + + ComponentConfig comp_b; + comp_b.name = "comp_b"; + comp_b.component_properties.application_profile.application_type = ApplicationType::Native; + comp_b.component_properties.application_profile.is_self_terminating = false; + comp_b.component_properties.ready_condition = ReadyCondition{ProcessState::Terminated}; + comp_b.component_properties.depends_on = {"comp_a"}; + comp_b.deployment_config.executable_path = "/opt/comp_b"; + comp_b.deployment_config.working_dir = "/tmp"; + comp_b.deployment_config.sandbox.uid = 0; + comp_b.deployment_config.sandbox.gid = 0; + comp_b.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_b.deployment_config.sandbox.scheduling_priority = 0; + + std::vector components; + components.push_back(std::move(comp_a)); + components.push_back(std::move(comp_b)); + + RunTargetConfig startup; + startup.name = "Startup"; + startup.depends_on = {"comp_b"}; + startup.transition_timeout_ms = 5000; + startup.recovery_action.run_target = "fallback_run_target"; + + std::vector run_targets; + run_targets.push_back(std::move(startup)); + + FallbackRunTargetConfig fallback; + fallback.transition_timeout_ms = 1500; + AliveSupervisionConfig alive; + alive.evaluation_cycle_ms = 500; + + auto config = ConfigBuilder{} + .setComponents(std::move(components)) + .setRunTargets(std::move(run_targets)) + .setInitialRunTarget("Startup") + .setFallbackRunTarget(std::move(fallback)) + .setAliveSupervision(alive) + .build(); + + ConfigurationAdapter adapter; + adapter.initialize(config); + + IdentifierHash pg_name{"MainPG"}; + auto result = adapter.getOsProcessDependencies(pg_name, 1U); + ASSERT_TRUE(result.has_value()); + const auto* deps = *result; + ASSERT_THAT(deps->size(), Eq(1U)); + EXPECT_THAT((*deps)[0].process_state_, Eq(score::lcm::ProcessState::kRunning)) + << "comp_a has no ready_condition, so dependency should default to Running"; + + adapter.deinitialize(); +} + +TEST(ConfigurationAdapterFallbackTest, FallbackRunTargetResolvesDependenciesRecursively) +{ + RecordProperty("Description", + "Fallback run target resolves transitive component dependencies."); + RecordProperty("TestType", "interface-test"); + RecordProperty("DerivationTechnique", "explorative-testing"); + + ComponentConfig comp_a; + comp_a.name = "comp_a"; + comp_a.component_properties.application_profile.application_type = ApplicationType::Native; + comp_a.component_properties.application_profile.is_self_terminating = false; + comp_a.deployment_config.executable_path = "/opt/comp_a"; + comp_a.deployment_config.working_dir = "/tmp"; + comp_a.deployment_config.sandbox.uid = 0; + comp_a.deployment_config.sandbox.gid = 0; + comp_a.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_a.deployment_config.sandbox.scheduling_priority = 0; + + ComponentConfig comp_b; + comp_b.name = "comp_b"; + comp_b.component_properties.application_profile.application_type = ApplicationType::Native; + comp_b.component_properties.application_profile.is_self_terminating = false; + comp_b.component_properties.depends_on = {"comp_a"}; + comp_b.deployment_config.executable_path = "/opt/comp_b"; + comp_b.deployment_config.working_dir = "/tmp"; + comp_b.deployment_config.sandbox.uid = 0; + comp_b.deployment_config.sandbox.gid = 0; + comp_b.deployment_config.sandbox.scheduling_policy = SCHED_OTHER; + comp_b.deployment_config.sandbox.scheduling_priority = 0; + + std::vector components; + components.push_back(std::move(comp_a)); + components.push_back(std::move(comp_b)); + + RunTargetConfig startup; + startup.name = "Startup"; + startup.depends_on = {"comp_b"}; + startup.transition_timeout_ms = 5000; + startup.recovery_action.run_target = "fallback_run_target"; + + std::vector run_targets; + run_targets.push_back(std::move(startup)); + + FallbackRunTargetConfig fallback; + fallback.depends_on = {"comp_b"}; + fallback.transition_timeout_ms = 1500; + AliveSupervisionConfig alive; + alive.evaluation_cycle_ms = 500; + + auto config = ConfigBuilder{} + .setComponents(std::move(components)) + .setRunTargets(std::move(run_targets)) + .setInitialRunTarget("Startup") + .setFallbackRunTarget(std::move(fallback)) + .setAliveSupervision(alive) + .build(); + + ConfigurationAdapter adapter; + adapter.initialize(config); + + score::lcm::internal::ProcessGroupStateID fallback_id{ + IdentifierHash{"MainPG"}, IdentifierHash{"MainPG/fallback_run_target"}}; + + auto result = adapter.getProcessIndexesList(fallback_id); + ASSERT_TRUE(result.has_value()); + const auto& indexes = **result; + + EXPECT_THAT(indexes.size(), Eq(2U)) + << "fallback depends on comp_b which depends on comp_a; both should be resolved"; + bool has_comp_a = std::find(indexes.begin(), indexes.end(), 0U) != indexes.end(); + bool has_comp_b = std::find(indexes.begin(), indexes.end(), 1U) != indexes.end(); + EXPECT_TRUE(has_comp_a) << "comp_a (transitive dep of comp_b) should be in fallback indexes"; + EXPECT_TRUE(has_comp_b) << "comp_b (direct dep of fallback) should be in fallback indexes"; + + adapter.deinitialize(); +} + } // namespace } // namespace score::mw::launch_manager::configuration diff --git a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp index ecf8736c0..a339271ae 100644 --- a/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp +++ b/score/launch_manager/src/daemon/src/configuration/details/flatbuffer_type_converters.cpp @@ -542,6 +542,11 @@ score::cpp::expected convertAliveS LM_LOG_ERROR() << "Invalid value for AliveSupervision::evaluation_cycle"; return score::cpp::make_unexpected(evaluation_cycle_ms.error()); } + if (*evaluation_cycle_ms == 0U) + { + LM_LOG_ERROR() << "AliveSupervision::evaluation_cycle must not be zero"; + return score::cpp::make_unexpected(IConfigLoader::Error::InvalidFormat); + } return AliveSupervisionConfig{*evaluation_cycle_ms}; } From 1bc241c7853681883de048d93b699776e664faa0 Mon Sep 17 00:00:00 2001 From: "Quiring Paul (ETAS-ECM/XPC-Fe2)" Date: Tue, 23 Jun 2026 16:47:51 +0200 Subject: [PATCH 7/7] Apply suggtestions from reivew --- .../docs/user_guide/getting_started.rst | 3 ++- .../alive_monitor/details/factory/FlatCfgFactory.cpp | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/score/launch_manager/docs/user_guide/getting_started.rst b/score/launch_manager/docs/user_guide/getting_started.rst index f8b89e1fd..cc3b80158 100644 --- a/score/launch_manager/docs/user_guide/getting_started.rst +++ b/score/launch_manager/docs/user_guide/getting_started.rst @@ -40,7 +40,8 @@ Add a ``launch_manager_config`` target to your ``BUILD`` file: flatbuffer_out_dir = "etc", ) -===================== +Write a Configuration File +========================== Create a JSON configuration file that describes the components to launch, the run targets, and the alive supervision settings. diff --git a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp index f0c7d608f..24a038018 100644 --- a/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp +++ b/score/launch_manager/src/daemon/src/alive_monitor/details/factory/FlatCfgFactory.cpp @@ -184,16 +184,15 @@ bool FlatCfgFactory::createAliveIf( std::vector &f_processStates_r) { bool isSuccess{true}; try { - uint32_t index{0U}; - f_interfaces_r.reserve(f_interfaceIpcs_r.size()); - for (auto &interfaceIpc : f_interfaceIpcs_r) { + f_interfaces_r.reserve(supervised_components_.size()); + for (std::size_t compIndex = 0; compIndex < supervised_components_.size(); + ++compIndex) { + auto &interfaceIpc = f_interfaceIpcs_r.at(compIndex); f_interfaces_r.emplace_back(interfaceIpc, interfaceIpc.getPath().data()); - f_processStates_r.at(static_cast(index)) - .attachObserver(f_interfaces_r.back()); + f_processStates_r.at(compIndex).attachObserver(f_interfaces_r.back()); logger_r.LogDebug() << "Successfully created MonitorInterface:" << f_interfaces_r.back().getInterfaceName(); - index++; } logger_r.LogDebug() << "Number of constructed Monitor interfaces:"