diff --git a/src/core/sm/launcher/itf/runtime.hpp b/src/core/sm/launcher/itf/runtime.hpp index 97b6423bf..8b91ab602 100644 --- a/src/core/sm/launcher/itf/runtime.hpp +++ b/src/core/sm/launcher/itf/runtime.hpp @@ -48,6 +48,18 @@ class RuntimeItf : public monitoring::InstanceMonitoringProviderItf { */ virtual Error GetRuntimeInfo(RuntimeInfo& runtimeInfo) const = 0; + /** + * Initializes instances. + * + * Launcher provides list of known instances to runtime at startup. Runtime should stop all instances that are not + * in the list and properly initialize already running instances. Runtime should not start any instance at this + * stage, it should only prepare them for future start. + * + * @param instancesInfo instances info. + * @return Error. + */ + virtual Error InitInstances(const Array& instancesInfo) = 0; + /** * Start instance. * diff --git a/src/core/sm/launcher/launcher.cpp b/src/core/sm/launcher/launcher.cpp index edcfdfa34..a9ed66b9c 100644 --- a/src/core/sm/launcher/launcher.cpp +++ b/src/core/sm/launcher/launcher.cpp @@ -79,6 +79,8 @@ Error Launcher::Start() return AOS_ERROR_WRAP(err); } + InitInstances(*storedInstances); + lock.Unlock(); LoadInstancesData(*storedInstances); @@ -361,6 +363,33 @@ void Launcher::OnDisconnect() StartTTLTimer(); } +void Launcher::InitInstances(const Array& instancesInfo) +{ + LOG_DBG() << "Init instances" << Log::Field("numInstances", instancesInfo.Size()); + + for (auto& it : mRuntimes) { + auto runtimeInstances = MakeUnique(&mAllocator); + + for (const auto& instanceInfo : instancesInfo) { + if (instanceInfo.mRuntimeID != it.mSecond) { + continue; + } + + if (auto err = runtimeInstances->PushBack(instanceInfo); !err.IsNone()) { + LOG_ERR() << "Failed to add instance to runtime init list" << Log::Field("instance", instanceInfo) + << Log::Field(AOS_ERROR_WRAP(err)); + + break; + } + } + + if (auto err = it.mFirst->InitInstances(*runtimeInstances); !err.IsNone()) { + LOG_ERR() << "Failed to init instances" << Log::Field("runtimeID", it.mSecond) + << Log::Field(AOS_ERROR_WRAP(err)); + } + } +} + void Launcher::RunRebootThread() { while (true) { diff --git a/src/core/sm/launcher/launcher.hpp b/src/core/sm/launcher/launcher.hpp index 954213834..801caafd3 100644 --- a/src/core/sm/launcher/launcher.hpp +++ b/src/core/sm/launcher/launcher.hpp @@ -173,7 +173,7 @@ class Launcher : public LauncherItf, static constexpr auto cMaxNumSubscribers = 4; static constexpr auto cAllocatorSize = 2 * sizeof(StaticArray) - + 2 * sizeof(InstanceInfoArray) + sizeof(InstanceStatusArray) + + 3 * sizeof(InstanceInfoArray) + sizeof(InstanceStatusArray) + cMaxNumConcurrentItems * (sizeof(oci::ImageConfig) + sizeof(oci::ItemConfig) + Max(sizeof(StaticString) + sizeof(oci::ImageManifest), @@ -181,7 +181,7 @@ class Launcher : public LauncherItf, + Max(sizeof(StaticArray), sizeof(StaticArray) + sizeof(StaticArray)); - static constexpr auto cMaxNumAllocations = 4 + cMaxNumConcurrentItems * 4; + static constexpr auto cMaxNumAllocations = 5 + cMaxNumConcurrentItems * 4; void OnConnect() override; void OnDisconnect() override; @@ -233,6 +233,7 @@ class Launcher : public LauncherItf, void StartTTLTimer(); void StopExpiredInstances(UniqueLock& lock); void SendNodeInstancesStatuses(); + void InitInstances(const Array& instancesInfo); StaticAllocator mAllocator; StaticArray mSubscribers; diff --git a/src/core/sm/launcher/tests/launcher.cpp b/src/core/sm/launcher/tests/launcher.cpp index 429ca0b6b..b9da0b2ae 100644 --- a/src/core/sm/launcher/tests/launcher.cpp +++ b/src/core/sm/launcher/tests/launcher.cpp @@ -162,11 +162,13 @@ class LauncherTest : public Test { EXPECT_CALL(mRuntime0, Stop).WillRepeatedly(Return(ErrorEnum::eNone)); EXPECT_CALL(mRuntime0, GetRuntimeInfo) .WillRepeatedly(DoAll(SetArgReferee<0>(CreateRuntimeInfo("runtime0")), Return(ErrorEnum::eNone))); + EXPECT_CALL(mRuntime0, InitInstances).WillRepeatedly(Return(ErrorEnum::eNone)); EXPECT_CALL(mRuntime1, Start).WillRepeatedly(Return(ErrorEnum::eNone)); EXPECT_CALL(mRuntime1, Stop).WillRepeatedly(Return(ErrorEnum::eNone)); EXPECT_CALL(mRuntime1, GetRuntimeInfo) .WillRepeatedly(DoAll(SetArgReferee<0>(CreateRuntimeInfo("runtime1")), Return(ErrorEnum::eNone))); + EXPECT_CALL(mRuntime1, InitInstances).WillRepeatedly(Return(ErrorEnum::eNone)); mImageManifest.mItemConfig.EmplaceValue(); @@ -246,6 +248,63 @@ TEST_F(LauncherTest, NoStoredInstancesOnModuleStart) ASSERT_TRUE(err.IsNone()) << tests::utils::ErrorToStr(err); } +TEST_F(LauncherTest, InitInstances) +{ + const std::vector cStoredInfos = { + CreateInstanceInfo("item0", 0, "1.0.0", "runtime0"), + CreateInstanceInfo("item1", 1, "1.0.0", "runtime1"), + CreateInstanceInfo("item2", 2, "1.0.0", "runtime0"), + }; + + const std::vector cRuntime0Infos = {cStoredInfos[0], cStoredInfos[2]}; + const std::vector cRuntime1Infos = {cStoredInfos[1]}; + + mStorage.Init(cStoredInfos); + + auto err = mLauncher.Init(GetRuntimesArray(), mImageManager, mSender, mStorage, mOCISpec, mItemInfoProvider, + mCloudConnection, mNetworkManager, mInstanceIDProvider, mResourceInfoProvider); + ASSERT_TRUE(err.IsNone()) << tests::utils::ErrorToStr(err); + + EXPECT_CALL(mRuntime0, InitInstances(Array(&cRuntime0Infos.front(), cRuntime0Infos.size()))) + .WillOnce(Return(ErrorEnum::eNone)); + EXPECT_CALL(mRuntime1, InitInstances(Array(&cRuntime1Infos.front(), cRuntime1Infos.size()))) + .WillOnce(Return(ErrorEnum::eNone)); + + EXPECT_CALL(mRuntime0, StartInstance) + .WillRepeatedly(Invoke([](const InstanceInfo& instance, InstanceStatus& status) { + SetInstanceStatus(instance, InstanceStateEnum::eActive, status); + + return ErrorEnum::eNone; + })); + + EXPECT_CALL(mRuntime1, StartInstance) + .WillRepeatedly(Invoke([](const InstanceInfo& instance, InstanceStatus& status) { + SetInstanceStatus(instance, InstanceStateEnum::eActive, status); + + return ErrorEnum::eNone; + })); + + err = mLauncher.Start(); + ASSERT_TRUE(err.IsNone()) << tests::utils::ErrorToStr(err); + + EXPECT_CALL(mRuntime0, StopInstance) + .WillRepeatedly(Invoke([](const InstanceIdent& instance, InstanceStatus& status) { + SetInstanceStatus(instance, InstanceStateEnum::eInactive, status); + + return ErrorEnum::eNone; + })); + + EXPECT_CALL(mRuntime1, StopInstance) + .WillRepeatedly(Invoke([](const InstanceIdent& instance, InstanceStatus& status) { + SetInstanceStatus(instance, InstanceStateEnum::eInactive, status); + + return ErrorEnum::eNone; + })); + + err = mLauncher.Stop(); + ASSERT_TRUE(err.IsNone()) << tests::utils::ErrorToStr(err); +} + TEST_F(LauncherTest, SendActiveComponentNodeInstancesStatusOnModuleStart) { const std::vector cRuntime0Components = { diff --git a/src/core/sm/launcher/tests/mocks/runtimemock.hpp b/src/core/sm/launcher/tests/mocks/runtimemock.hpp index 8654e1acb..c3a4bd4a7 100644 --- a/src/core/sm/launcher/tests/mocks/runtimemock.hpp +++ b/src/core/sm/launcher/tests/mocks/runtimemock.hpp @@ -21,6 +21,7 @@ class RuntimeMock : public RuntimeItf { MOCK_METHOD(Error, Start, (), (override)); MOCK_METHOD(Error, Stop, (), (override)); MOCK_METHOD(Error, GetRuntimeInfo, (RuntimeInfo&), (const, override)); + MOCK_METHOD(Error, InitInstances, (const Array&), (override)); MOCK_METHOD(Error, StartInstance, (const InstanceInfo&, InstanceStatus&), (override)); MOCK_METHOD(Error, StopInstance, (const InstanceIdent&, InstanceStatus&), (override)); MOCK_METHOD(Error, Reboot, (), (override));