diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index a5fa2f24..073bd557 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -41,6 +41,10 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} fetch-depth: 0 + - name: Static analysis + run: | + ./build.sh lint --aos-service cm --aos-service iam --aos-service sm + - name: Install SonarQube build wrapper uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6 @@ -56,10 +60,6 @@ jobs: run: | ./build.sh coverage --aos-service cm --aos-service iam --aos-service sm - - name: Static analysis - run: | - ./build.sh lint --aos-service cm --aos-service iam --aos-service sm - - name: Upload codecov report uses: codecov/codecov-action@v4 with: diff --git a/src/cm/config/config.cpp b/src/cm/config/config.cpp index 4e6865c5..70a682c2 100644 --- a/src/cm/config/config.cpp +++ b/src/cm/config/config.cpp @@ -28,7 +28,7 @@ constexpr auto cDefaultLauncherInstanceTTL = "30d"; constexpr auto cDefaultLauncherNodesConnectionTimeout = "10m"; constexpr auto cDefaultMonitoringSendPeriod = "1m"; constexpr auto cDefaultSMConnectionTimeout = "1m"; -constexpr auto cDefaultUnitStatusSendTimeout = "30s"; +constexpr auto cDefaultUnitStatusSendTimeout = "10s"; constexpr auto cDefaultUpdateItemTTL = "30d"; constexpr auto cDefaultRemoveOutdatedPeriod = "24h"; constexpr auto cDefaultMigrationPath = "/usr/share/aos/communicationmanager/migration"; diff --git a/src/cm/config/tests/config.cpp b/src/cm/config/tests/config.cpp index c9559e81..016ad054 100644 --- a/src/cm/config/tests/config.cpp +++ b/src/cm/config/tests/config.cpp @@ -168,7 +168,7 @@ TEST_F(CMConfigTest, ParseMinimalConfigWithDefaults) EXPECT_EQ(config.mStateDir, (std::filesystem::path("workingDir") / "states").string()); EXPECT_EQ(config.mUnitConfigFile, (std::filesystem::path("workingDir") / "aos_unit.cfg").string()); - EXPECT_EQ(config.mUnitStatusSendTimeout, aos::Time::cSeconds * 30); + EXPECT_EQ(config.mUnitStatusSendTimeout, aos::Time::cSeconds * 10); EXPECT_EQ(config.mCloudResponseWaitTimeout, aos::Time::cSeconds * 10); EXPECT_EQ(config.mMonitoring.mSendPeriod, aos::Time::cMinutes * 1); diff --git a/src/cm/database/database.cpp b/src/cm/database/database.cpp index f1f561f8..14abd9e2 100644 --- a/src/cm/database/database.cpp +++ b/src/cm/database/database.cpp @@ -656,8 +656,8 @@ Error Database::AddItem(const imagemanager::ItemInfo& item) ImageManagerItemInfoRow row; FromAos(item, row); - *mSession - << "INSERT INTO imagemanager (itemID, version, indexDigest, state, timestamp) VALUES (?, ?, ?, ?, ?);", + *mSession << "INSERT INTO imagemanager (itemID, type, version, indexDigest, state, timestamp) VALUES " + "(?, ?, ?, ?, ?, ?);", bind(row), now; } catch (const std::exception& e) { return AOS_ERROR_WRAP(common::utils::ToAosError(e)); @@ -713,7 +713,7 @@ Error Database::GetAllItemsInfos(Array& items) try { std::vector rows; - *mSession << "SELECT itemID, version, indexDigest, state, timestamp FROM imagemanager;", into(rows), now; + *mSession << "SELECT itemID, type, version, indexDigest, state, timestamp FROM imagemanager;", into(rows), now; auto itemInfo = std::make_unique(); @@ -737,7 +737,7 @@ Error Database::GetItemInfos(const String& id, Array& it try { std::vector rows; - *mSession << "SELECT itemID, version, indexDigest, state, timestamp FROM imagemanager WHERE itemID = ?;", + *mSession << "SELECT itemID, type, version, indexDigest, state, timestamp FROM imagemanager WHERE itemID = ?;", bind(id.CStr()), into(rows), now; auto itemInfo = std::make_unique(); @@ -874,6 +874,7 @@ void Database::CreateTables() *mSession << "CREATE TABLE IF NOT EXISTS imagemanager (" "itemID TEXT," + "type TEXT," "version TEXT," "indexDigest TEXT," "state TEXT," @@ -1093,6 +1094,7 @@ void Database::FromAos(const imagemanager::ItemInfo& src, ImageManagerItemInfoRo { dst.set(src.mItemID.CStr()); dst.set(src.mVersion.CStr()); + dst.set(src.mType.ToString().CStr()); dst.set(src.mIndexDigest.CStr()); dst.set(src.mState.ToString().CStr()); dst.set(src.mTimestamp.UnixNano()); @@ -1100,10 +1102,12 @@ void Database::FromAos(const imagemanager::ItemInfo& src, ImageManagerItemInfoRo void Database::ToAos(const ImageManagerItemInfoRow& src, imagemanager::ItemInfo& dst) { - dst.mItemID = src.get().c_str(); + dst.mItemID = src.get().c_str(); + auto err = dst.mType.FromString(src.get().c_str()); + AOS_ERROR_CHECK_AND_THROW(err, "failed to parse item type"); dst.mVersion = src.get().c_str(); dst.mIndexDigest = src.get().c_str(); - auto err = dst.mState.FromString(src.get().c_str()); + err = dst.mState.FromString(src.get().c_str()); AOS_ERROR_CHECK_AND_THROW(err, "failed to parse item state"); auto timestamp = src.get(); dst.mTimestamp = Time::Unix(timestamp / Time::cSeconds.Nanoseconds(), timestamp % Time::cSeconds.Nanoseconds()); diff --git a/src/cm/database/database.hpp b/src/cm/database/database.hpp index 86038ef0..1774397a 100644 --- a/src/cm/database/database.hpp +++ b/src/cm/database/database.hpp @@ -276,6 +276,10 @@ class Database : public DatabaseItf, public networkmanager::StorageItf { */ Error StoreDesiredStatus(const DesiredStatus& desiredStatus) override; + // + // updatemanager::StorageItf interface + // + /** * Stores update state in storage. * @@ -362,8 +366,16 @@ class Database : public DatabaseItf, public networkmanager::StorageItf { std::string, std::string, std::string, uint32_t, uint32_t, uint64_t, std::string, bool, std::string, std::string, std::string, std::string, size_t>; - enum class ImageManagerItemInfoColumns : int { eItemID = 0, eVersion, eIndexDigest, eState, eTimestamp }; - using ImageManagerItemInfoRow = Poco::Tuple; + enum class ImageManagerItemInfoColumns : int { + eItemID = 0, + eType, + eVersion, + eIndexDigest, + eState, + eTimestamp, + }; + using ImageManagerItemInfoRow + = Poco::Tuple; // make virtual for unit tests virtual int GetVersion() const; diff --git a/src/cm/database/tests/database.cpp b/src/cm/database/tests/database.cpp index d4a8f2f0..238761af 100644 --- a/src/cm/database/tests/database.cpp +++ b/src/cm/database/tests/database.cpp @@ -136,11 +136,12 @@ launcher::InstanceInfo CreateLauncherInstanceInfo(const char* itemID, const char } imagemanager::ItemInfo CreateImageManagerItemInfo( - const char* itemID, const char* version, const char* indexDigest, ItemState state) + const char* itemID, const UpdateItemType& type, const char* version, const char* indexDigest, ItemState state) { imagemanager::ItemInfo info; info.mItemID = itemID; + info.mType = type; info.mVersion = version; info.mIndexDigest = indexDigest; info.mState = state; @@ -677,15 +678,19 @@ TEST_F(CMDatabaseTest, ImageManagerAddItem) { ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); - auto item1 = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); - auto item2 = CreateImageManagerItemInfo("service1", "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); - auto item3 = CreateImageManagerItemInfo("service2", "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); + auto item1 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); + auto item2 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); + auto item3 = CreateImageManagerItemInfo( + "service2", UpdateItemTypeEnum::eService, "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); ASSERT_TRUE(mDB.AddItem(item1).IsNone()); ASSERT_TRUE(mDB.AddItem(item2).IsNone()); ASSERT_TRUE(mDB.AddItem(item3).IsNone()); - auto duplicateItem = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:xyz999", ItemStateEnum::eInstalled); + auto duplicateItem = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:xyz999", ItemStateEnum::eInstalled); ASSERT_FALSE(mDB.AddItem(duplicateItem).IsNone()); StaticArray items; @@ -699,9 +704,12 @@ TEST_F(CMDatabaseTest, ImageManagerRemoveItem) { ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); - auto item1 = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); - auto item2 = CreateImageManagerItemInfo("service1", "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); - auto item3 = CreateImageManagerItemInfo("service2", "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); + auto item1 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); + auto item2 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); + auto item3 = CreateImageManagerItemInfo( + "service2", UpdateItemTypeEnum::eService, "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); ASSERT_TRUE(mDB.AddItem(item1).IsNone()); ASSERT_TRUE(mDB.AddItem(item2).IsNone()); @@ -722,8 +730,10 @@ TEST_F(CMDatabaseTest, ImageManagerUpdateItemState) { ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); - auto item1 = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:abc123", ItemStateEnum::ePending); - auto item2 = CreateImageManagerItemInfo("service2", "1.0.0", "sha256:def456", ItemStateEnum::ePending); + auto item1 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:abc123", ItemStateEnum::ePending); + auto item2 = CreateImageManagerItemInfo( + "service2", UpdateItemTypeEnum::eService, "1.0.0", "sha256:def456", ItemStateEnum::ePending); ASSERT_TRUE(mDB.AddItem(item1).IsNone()); ASSERT_TRUE(mDB.AddItem(item2).IsNone()); @@ -756,9 +766,12 @@ TEST_F(CMDatabaseTest, ImageManagerGetItemsInfo) ASSERT_TRUE(mDB.GetAllItemsInfos(emptyItems).IsNone()); EXPECT_EQ(emptyItems.Size(), 0); - auto item1 = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); - auto item2 = CreateImageManagerItemInfo("service1", "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); - auto item3 = CreateImageManagerItemInfo("service2", "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); + auto item1 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); + auto item2 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); + auto item3 = CreateImageManagerItemInfo( + "service2", UpdateItemTypeEnum::eService, "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); ASSERT_TRUE(mDB.AddItem(item1).IsNone()); ASSERT_TRUE(mDB.AddItem(item2).IsNone()); @@ -775,9 +788,12 @@ TEST_F(CMDatabaseTest, ImageManagerGetItemsInfos) { ASSERT_TRUE(mDB.Init(mDatabaseConfig).IsNone()); - auto item1 = CreateImageManagerItemInfo("service1", "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); - auto item2 = CreateImageManagerItemInfo("service1", "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); - auto item3 = CreateImageManagerItemInfo("service2", "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); + auto item1 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "1.0.0", "sha256:abc123", ItemStateEnum::eInstalled); + auto item2 = CreateImageManagerItemInfo( + "service1", UpdateItemTypeEnum::eService, "2.0.0", "sha256:def456", ItemStateEnum::eInstalled); + auto item3 = CreateImageManagerItemInfo( + "service2", UpdateItemTypeEnum::eService, "1.0.0", "sha256:ghi789", ItemStateEnum::ePending); ASSERT_TRUE(mDB.AddItem(item1).IsNone()); ASSERT_TRUE(mDB.AddItem(item2).IsNone()); diff --git a/src/cm/smcontroller/smhandler.cpp b/src/cm/smcontroller/smhandler.cpp index cb590cb4..dbeaaf9a 100644 --- a/src/cm/smcontroller/smhandler.cpp +++ b/src/cm/smcontroller/smhandler.cpp @@ -38,9 +38,11 @@ SMHandler::SMHandler(grpc::ServerContext* void SMHandler::Start() { + std::lock_guard lock {mMutex}; + LOG_DBG() << "Start SM handler"; - mStopProcessing.store(false); + mStopProcessing = false; mSyncMessageSender.Init(mStream, cResponseTime); mSyncMessageSender.RegisterResponseHandler( @@ -54,25 +56,36 @@ void SMHandler::Start() dst.mutable_average_monitoring()->CopyFrom(src.average_monitoring()); }); - mProcessThread = std::thread([this]() { ProcessMessages(); }); + mReadThread = std::thread([this]() { ReadMessages(); }); + mMessageThread = std::thread([this]() { ProcessMessages(); }); } void SMHandler::Wait() { - if (mProcessThread.joinable()) { - mProcessThread.join(); + LOG_DBG() << "Wait SM handler"; + + if (mReadThread.joinable()) { + mReadThread.join(); + } + + if (mMessageThread.joinable()) { + mMessageThread.join(); } } void SMHandler::Stop() { + std::lock_guard lock {mMutex}; + LOG_DBG() << "Stop SM handler"; - mStopProcessing.store(true); + mStopProcessing = true; if (mContext) { mContext->TryCancel(); } + + mCondVar.notify_one(); } String SMHandler::GetNodeID() const @@ -213,13 +226,56 @@ Error SMHandler::UpdateNetworks(const Array& networkPar * Private **********************************************************************************************************************/ -Error SMHandler::ProcessMessages() +void SMHandler::ReadMessages() { try { servicemanager::v5::SMOutgoingMessages outgoingMsg; - while (!mStopProcessing.load() && mStream->Read(&outgoingMsg)) { + while (mStream->Read(&outgoingMsg)) { + if (auto err = mSyncMessageSender.ProcessResponse(outgoingMsg); err.HasValue()) { + if (!err->IsNone()) { + LOG_ERR() << "Failed to process response" << Log::Field("nodeID", GetNodeID()) + << Log::Field(AOS_ERROR_WRAP(*err)); + } + } else { + std::lock_guard lock {mMutex}; + + mMessageQueue.push(outgoingMsg); + mCondVar.notify_one(); + } + } + } catch (const std::exception& e) { + LOG_ERR() << "Handle incoming messages failed" << Log::Field(AOS_ERROR_WRAP(common::utils::ToAosError(e))); + } + + mConnStatusListener->OnNodeDisconnected(GetNodeID()); + + std::lock_guard lock {mMutex}; + + mStopProcessing = true; + mCondVar.notify_one(); +} + +void SMHandler::ProcessMessages() +{ + while (true) { + try { + std::unique_lock lock {mMutex}; + + mCondVar.wait(lock, [this]() { return mStopProcessing || !mMessageQueue.empty(); }); + + if (mStopProcessing) { + break; + } + Error err; + auto outgoingMsg = mMessageQueue.front(); + + mMessageQueue.pop(); + + // Process message without holding the lock to allow sending new messages in parallel + + lock.unlock(); if (outgoingMsg.has_sm_info()) { err = ProcessSMInfo(outgoingMsg.sm_info()); @@ -233,8 +289,6 @@ Error SMHandler::ProcessMessages() err = ProcessInstantMonitoring(outgoingMsg.instant_monitoring()); } else if (outgoingMsg.has_alert()) { err = ProcessAlert(outgoingMsg.alert()); - } else if (auto processErr = mSyncMessageSender.ProcessResponse(outgoingMsg); processErr.HasValue()) { - err = processErr.GetValue(); } else { LOG_WRN() << "Unknown message type received"; } @@ -242,14 +296,11 @@ Error SMHandler::ProcessMessages() if (!err.IsNone()) { LOG_ERR() << "Failed to process message" << Log::Field("nodeID", GetNodeID()) << Log::Field(err); } + } catch (const std::exception& e) { + LOG_ERR() << "Process message failed" << Log::Field("nodeID", GetNodeID()) + << Log::Field(AOS_ERROR_WRAP(common::utils::ToAosError(e))); } - } catch (const std::exception& e) { - LOG_ERR() << "Handle incoming messages failed" << Log::Field(AOS_ERROR_WRAP(common::utils::ToAosError(e))); } - - mConnStatusListener->OnNodeDisconnected(GetNodeID()); - - return ErrorEnum::eNone; } Error SMHandler::SendMessage(const servicemanager::v5::SMIncomingMessages& message) diff --git a/src/cm/smcontroller/smhandler.hpp b/src/cm/smcontroller/smhandler.hpp index b3dacdc3..7815e8ec 100644 --- a/src/cm/smcontroller/smhandler.hpp +++ b/src/cm/smcontroller/smhandler.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -181,8 +182,8 @@ class SMHandler { Error SendMessage(const servicemanager::v5::SMIncomingMessages& message); - // Message processing methods - Error ProcessMessages(); + void ReadMessages(); + void ProcessMessages(); Error ProcessSMInfo(const servicemanager::v5::SMInfo& smInfo); Error ProcessUpdateInstancesStatus(const servicemanager::v5::UpdateInstancesStatus& status); @@ -205,12 +206,15 @@ class SMHandler { nodeinfoprovider::SMInfoReceiverItf* mSMInfoReceiver {}; NodeConnectionStatusListenerItf* mConnStatusListener {}; - std::mutex mMutex; bool mCredentialListUpdated {}; grpc::ServerContext* mCtx {}; - std::thread mProcessThread; - std::atomic mStopProcessing {}; + std::mutex mMutex; + std::condition_variable mCondVar; + std::thread mReadThread; + std::thread mMessageThread; + bool mStopProcessing {}; + std::queue mMessageQueue; StaticString mNodeID; }; diff --git a/src/common/cloudprotocol/common.cpp b/src/common/cloudprotocol/common.cpp index de5fa155..6ad4717f 100644 --- a/src/common/cloudprotocol/common.cpp +++ b/src/common/cloudprotocol/common.cpp @@ -42,14 +42,14 @@ Poco::JSON::Object::Ptr CreateAosIdentity(const AosIdentity& identity) json->set("id", *identity.mID); } - if (identity.mType.has_value()) { - json->set("type", identity.mType->ToString().CStr()); - } - if (identity.mCodename.has_value()) { json->set("codename", *identity.mCodename); } + if (identity.mType.has_value()) { + json->set("type", identity.mType->ToString().CStr()); + } + if (identity.mTitle.has_value()) { json->set("title", *identity.mTitle); } diff --git a/src/common/cloudprotocol/tests/unitstatus.cpp b/src/common/cloudprotocol/tests/unitstatus.cpp index ccca64d1..aea7bd9b 100644 --- a/src/common/cloudprotocol/tests/unitstatus.cpp +++ b/src/common/cloudprotocol/tests/unitstatus.cpp @@ -189,11 +189,11 @@ TEST_F(CloudProtocolUnitStatus, Nodes) TEST_F(CloudProtocolUnitStatus, Items) { - constexpr auto cJSON - = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"items":[)" - R"({"item":{"id":"itemID1"},"version":"version1","state":"downloading"},)" - R"({"item":{"id":"itemID2"},"version":"version1","state":"installed"},)" - R"({"item":{"id":"itemID3"},"version":"version1","state":"failed","errorInfo":{"aosCode":1,"exitCode":0,"message":"test error"}}]})"; + constexpr auto cJSON = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"items":[)" + R"({"item":{"id":"itemID1","type":"service"},"version":"version1","state":"downloading"},)" + R"({"item":{"id":"itemID2","type":"service"},"version":"version1","state":"installed"},)" + R"({"item":{"id":"itemID3","type":"component"},"version":"version1","state":"failed",)" + R"("errorInfo":{"aosCode":1,"exitCode":0,"message":"test error"}}]})"; auto unitStatus = std::make_unique(); unitStatus->mCorrelationID = "id"; @@ -202,16 +202,19 @@ TEST_F(CloudProtocolUnitStatus, Items) unitStatus->mUpdateItems->EmplaceBack(); unitStatus->mUpdateItems->Back().mItemID = "itemID1"; + unitStatus->mUpdateItems->Back().mType = UpdateItemTypeEnum::eService; unitStatus->mUpdateItems->Back().mVersion = "version1"; unitStatus->mUpdateItems->Back().mState = ItemStateEnum::eDownloading; unitStatus->mUpdateItems->EmplaceBack(); unitStatus->mUpdateItems->Back().mItemID = "itemID2"; + unitStatus->mUpdateItems->Back().mType = UpdateItemTypeEnum::eService; unitStatus->mUpdateItems->Back().mVersion = "version1"; unitStatus->mUpdateItems->Back().mState = ItemStateEnum::eInstalled; unitStatus->mUpdateItems->EmplaceBack(); unitStatus->mUpdateItems->Back().mItemID = "itemID3"; + unitStatus->mUpdateItems->Back().mType = UpdateItemTypeEnum::eComponent; unitStatus->mUpdateItems->Back().mVersion = "version1"; unitStatus->mUpdateItems->Back().mState = ItemStateEnum::eFailed; unitStatus->mUpdateItems->Back().mError = Error(ErrorEnum::eFailed, "test error"); @@ -226,13 +229,17 @@ TEST_F(CloudProtocolUnitStatus, Items) TEST_F(CloudProtocolUnitStatus, Instances) { - constexpr auto cJSON - = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"instances":[)" - R"({"item":{"id":"itemID1"},"subject":{"id":"subjectID1"},"version":"version1","instances":[)" - R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},"instance":1,"stateChecksum":"12345678","state":"active"},)" - R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},"instance":2,"state":"failed","errorInfo":{"aosCode":1,"exitCode":0,"message":""}}]},)" - R"({"item":{"id":"itemID2"},"subject":{"id":"subjectID2"},"version":"version2","instances":[)" - R"({"node":{"codename":"nodeID2"},"runtime":{"codename":"runtimeID2"},"instance":1,"state":"activating"}]}]})"; + constexpr auto cJSON = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"instances":[)" + R"({"item":{"id":"itemID1","type":"service"},"subject":{"id":"subjectID1"},)" + R"("version":"version1","instances":[)" + R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},)" + R"("instance":1,"stateChecksum":"12345678","state":"active"},)" + R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},)" + R"("instance":2,"state":"failed","errorInfo":{"aosCode":1,"exitCode":0,"message":""}}]},)" + R"({"item":{"id":"itemID2","type":"component"},"subject":{"id":"subjectID2"},)" + R"("version":"version2","instances":[)" + R"({"node":{"codename":"nodeID2"},"runtime":{"codename":"runtimeID2"},)" + R"("instance":1,"state":"activating"}]}]})"; auto unitStatus = std::make_unique(); unitStatus->mCorrelationID = "id"; @@ -241,6 +248,7 @@ TEST_F(CloudProtocolUnitStatus, Instances) unitStatus->mInstances->EmplaceBack(); unitStatus->mInstances->Back().mItemID = "itemID1"; + unitStatus->mInstances->Back().mType = UpdateItemTypeEnum::eService; unitStatus->mInstances->Back().mSubjectID = "subjectID1"; unitStatus->mInstances->Back().mVersion = "version1"; @@ -260,6 +268,7 @@ TEST_F(CloudProtocolUnitStatus, Instances) unitStatus->mInstances->EmplaceBack(); unitStatus->mInstances->Back().mItemID = "itemID2"; + unitStatus->mInstances->Back().mType = UpdateItemTypeEnum::eComponent; unitStatus->mInstances->Back().mSubjectID = "subjectID2"; unitStatus->mInstances->Back().mVersion = "version2"; @@ -279,13 +288,17 @@ TEST_F(CloudProtocolUnitStatus, Instances) TEST_F(CloudProtocolUnitStatus, PreinstalledInstances) { - constexpr auto cJSON - = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"instances":[)" - R"({"item":{"id":"itemID1"},"subject":{"id":"subjectID1"},"version":"version1","instances":[)" - R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},"instance":1,"stateChecksum":"12345678","state":"active"},)" - R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},"instance":2,"state":"failed","errorInfo":{"aosCode":1,"exitCode":0,"message":""}}]},)" - R"({"item":{"codename":"itemID2"},"subject":{"codename":"subjectID2"},"version":"version2","instances":[)" - R"({"node":{"codename":"nodeID2"},"runtime":{"codename":"runtimeID2"},"instance":1,"state":"activating"}]}]})"; + constexpr auto cJSON = R"({"messageType":"unitStatus","correlationId":"id","isDeltaInfo":false,"instances":[)" + R"({"item":{"id":"itemID1","type":"service"},"subject":{"id":"subjectID1"},)" + R"("version":"version1","instances":[)" + R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},)" + R"("instance":1,"stateChecksum":"12345678","state":"active"},)" + R"({"node":{"codename":"nodeID1"},"runtime":{"codename":"runtimeID1"},)" + R"("instance":2,"state":"failed","errorInfo":{"aosCode":1,"exitCode":0,"message":""}}]},)" + R"({"item":{"codename":"itemID2","type":"component"},"subject":{"codename":"subjectID2"},)" + R"("version":"version2","instances":[)" + R"({"node":{"codename":"nodeID2"},"runtime":{"codename":"runtimeID2"},)" + R"("instance":1,"state":"activating"}]}]})"; auto unitStatus = std::make_unique(); unitStatus->mCorrelationID = "id"; @@ -294,6 +307,7 @@ TEST_F(CloudProtocolUnitStatus, PreinstalledInstances) unitStatus->mInstances->EmplaceBack(); unitStatus->mInstances->Back().mItemID = "itemID1"; + unitStatus->mInstances->Back().mType = UpdateItemTypeEnum::eService; unitStatus->mInstances->Back().mSubjectID = "subjectID1"; unitStatus->mInstances->Back().mVersion = "version1"; @@ -313,6 +327,7 @@ TEST_F(CloudProtocolUnitStatus, PreinstalledInstances) unitStatus->mInstances->EmplaceBack(); unitStatus->mInstances->Back().mItemID = "itemID2"; + unitStatus->mInstances->Back().mType = UpdateItemTypeEnum::eComponent; unitStatus->mInstances->Back().mSubjectID = "subjectID2"; unitStatus->mInstances->Back().mVersion = "version2"; unitStatus->mInstances->Back().mPreinstalled = true; diff --git a/src/common/cloudprotocol/unitconfig.cpp b/src/common/cloudprotocol/unitconfig.cpp index 0c5edc81..6da88766 100644 --- a/src/common/cloudprotocol/unitconfig.cpp +++ b/src/common/cloudprotocol/unitconfig.cpp @@ -207,8 +207,10 @@ Error ToJSON(const NodeConfig& nodeConfig, Poco::JSON::Object& json) AosIdentity identity; - identity.mCodename = nodeConfig.mNodeID.CStr(); - json.set("node", CreateAosIdentity(identity)); + if (!nodeConfig.mNodeID.IsEmpty()) { + identity.mCodename = nodeConfig.mNodeID.CStr(); + json.set("node", CreateAosIdentity(identity)); + } identity.mCodename = nodeConfig.mNodeType.CStr(); json.set("nodeGroupSubject", CreateAosIdentity(identity)); @@ -221,7 +223,10 @@ Error ToJSON(const NodeConfig& nodeConfig, Poco::JSON::Object& json) json.set("resourceRatios", ResourceRatiosToJSON(*nodeConfig.mResourceRatios)); } - json.set("labels", utils::ToJsonArray(nodeConfig.mLabels, utils::ToStdString)); + if (nodeConfig.mLabels.Size() > 0) { + json.set("labels", utils::ToJsonArray(nodeConfig.mLabels, utils::ToStdString)); + } + json.set("priority", nodeConfig.mPriority); return ErrorEnum::eNone; @@ -249,7 +254,7 @@ Error FromJSON(const common::utils::CaseInsensitiveObjectWrapper& json, NodeConf AOS_ERROR_CHECK_AND_THROW(err, "can't parse codename"); } - { + if (json.Has("node")) { AosIdentity identity; auto err = ParseAosIdentity(json.GetObject("node"), identity); @@ -276,7 +281,9 @@ Error FromJSON(const common::utils::CaseInsensitiveObjectWrapper& json, NodeConf AOS_ERROR_CHECK_AND_THROW(err, "can't parse labels"); } - nodeConfig.mPriority = json.GetValue("priority"); + if (json.Has("priority")) { + nodeConfig.mPriority = json.GetValue("priority"); + } return ErrorEnum::eNone; } catch (const std::exception& e) { @@ -287,8 +294,8 @@ Error FromJSON(const common::utils::CaseInsensitiveObjectWrapper& json, NodeConf Error ToJSON(const UnitConfig& unitConfig, Poco::JSON::Object& json) { try { - json.set("version", unitConfig.mVersion.CStr()); json.set("formatVersion", unitConfig.mFormatVersion.CStr()); + json.set("version", unitConfig.mVersion.CStr()); json.set("nodes", common::utils::ToJsonArray(unitConfig.mNodes, [](const auto& nodeConfig) { auto nodeJson = Poco::makeShared(Poco::JSON_PRESERVE_KEY_ORDER); @@ -307,12 +314,12 @@ Error ToJSON(const UnitConfig& unitConfig, Poco::JSON::Object& json) Error FromJSON(const utils::CaseInsensitiveObjectWrapper& json, UnitConfig& unitConfig) { try { - auto err = unitConfig.mVersion.Assign(json.GetValue("version").c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "parsed version length exceeds application limit"); - - err = unitConfig.mFormatVersion.Assign(json.GetValue("formatVersion").c_str()); + auto err = unitConfig.mFormatVersion.Assign(json.GetValue("formatVersion").c_str()); AOS_ERROR_CHECK_AND_THROW(err, "parsed format version length exceeds application limit"); + err = unitConfig.mVersion.Assign(json.GetValue("version").c_str()); + AOS_ERROR_CHECK_AND_THROW(err, "parsed version length exceeds application limit"); + common::utils::ForEach(json, "nodes", [&unitConfig](const auto& value) { auto err = unitConfig.mNodes.EmplaceBack(); AOS_ERROR_CHECK_AND_THROW(err, "can't create node config"); diff --git a/src/common/cloudprotocol/unitstatus.cpp b/src/common/cloudprotocol/unitstatus.cpp index 4b76eb47..ef2674b8 100644 --- a/src/common/cloudprotocol/unitstatus.cpp +++ b/src/common/cloudprotocol/unitstatus.cpp @@ -25,7 +25,10 @@ Poco::JSON::Object::Ptr UnitConfigToJSON(const UnitConfigStatus& unitConfigStatu { auto json = Poco::makeShared(Poco::JSON_PRESERVE_KEY_ORDER); - json->set("version", unitConfigStatus.mVersion.CStr()); + if (!unitConfigStatus.mVersion.IsEmpty()) { + json->set("version", unitConfigStatus.mVersion.CStr()); + } + json->set("state", unitConfigStatus.mState.ToString().CStr()); if (!unitConfigStatus.mError.IsNone()) { @@ -178,7 +181,8 @@ Poco::JSON::Object::Ptr NodeInfoToJSON(const UnitNodeInfo& nodeInfo) Poco::JSON::Object::Ptr UpdateItemToJSON(const UpdateItemStatus& status) { AosIdentity identity; - identity.mID = status.mItemID.CStr(); + identity.mID = status.mItemID.CStr(); + identity.mType = status.mType; auto json = Poco::makeShared(Poco::JSON_PRESERVE_KEY_ORDER); @@ -211,6 +215,8 @@ Poco::JSON::Object::Ptr InstanceToJSON(const UnitInstancesStatuses& statuses) identity.mID = statuses.mItemID.CStr(); } + identity.mType = statuses.mType; + json->set("item", CreateAosIdentity(identity)); } diff --git a/src/common/pbconvert/tests/sm.cpp b/src/common/pbconvert/tests/sm.cpp index 35e43abb..5aeb3b69 100644 --- a/src/common/pbconvert/tests/sm.cpp +++ b/src/common/pbconvert/tests/sm.cpp @@ -692,9 +692,8 @@ TEST_F(PBConvertSMTest, ConvertSMInfoFromProto) TEST_F(PBConvertSMTest, ConvertNodeConfigToCheckNodeConfigProto) { - static constexpr auto cExpectedNodeConfigJSON - = R"({"version":"2.5.0","node":{"codename":"config-node"},)" - R"("nodeGroupSubject":{"codename":"main"},"labels":[],"priority":0})"; + static constexpr auto cExpectedNodeConfigJSON = R"({"version":"2.5.0","node":{"codename":"config-node"},)" + R"("nodeGroupSubject":{"codename":"main"},"priority":0})"; NodeConfig config; @@ -713,9 +712,8 @@ TEST_F(PBConvertSMTest, ConvertNodeConfigToCheckNodeConfigProto) TEST_F(PBConvertSMTest, ConvertNodeConfigToSetNodeConfigProto) { - static constexpr auto cExpectedNodeConfigJSON - = R"({"version":"3.0.0","node":{"codename":"config-node"},)" - R"("nodeGroupSubject":{"codename":"main"},"labels":[],"priority":0})"; + static constexpr auto cExpectedNodeConfigJSON = R"({"version":"3.0.0","node":{"codename":"config-node"},)" + R"("nodeGroupSubject":{"codename":"main"},"priority":0})"; NodeConfig config; diff --git a/src/common/utils/fsplatform.cpp b/src/common/utils/fsplatform.cpp index 7b0ab794..8f7f0c71 100644 --- a/src/common/utils/fsplatform.cpp +++ b/src/common/utils/fsplatform.cpp @@ -56,7 +56,7 @@ RetWithError FSPlatform::GetAvailableSize(const String& dir) const return size_t(st.f_bavail) * st.f_frsize; } -Error FSPlatform::SetUserQuota(const String& path, size_t quota, size_t uid) const +Error FSPlatform::SetUserQuota(const String& path, uid_t uid, size_t quota) const { if (quota == 0) { return ErrorEnum::eNone; @@ -72,7 +72,7 @@ Error FSPlatform::SetUserQuota(const String& path, size_t quota, size_t uid) con dqblk dq {}; - dq.dqb_bhardlimit = quota; + dq.dqb_bhardlimit = (quota + 1023) / 1024; dq.dqb_valid = QIF_BLIMITS; if (auto res diff --git a/src/common/utils/fsplatform.hpp b/src/common/utils/fsplatform.hpp index 411933eb..e002200a 100644 --- a/src/common/utils/fsplatform.hpp +++ b/src/common/utils/fsplatform.hpp @@ -49,11 +49,11 @@ class FSPlatform : public fs::FSPlatformItf { * Sets user quota for the given path. * * @param path path to set quota for. - * @param quota quota size in bytes. * @param uid user ID. + * @param quota quota size in bytes. * @return Error. */ - Error SetUserQuota(const String& path, size_t quota, size_t uid) const override; + Error SetUserQuota(const String& path, uid_t uid, size_t quota) const override; /** * Changes the owner of a file or directory. diff --git a/src/sm/launcher/runtimes/container/monitoring.cpp b/src/sm/launcher/runtimes/container/monitoring.cpp index 71d4b918..2e75c27a 100644 --- a/src/sm/launcher/runtimes/container/monitoring.cpp +++ b/src/sm/launcher/runtimes/container/monitoring.cpp @@ -205,7 +205,7 @@ size_t Monitoring::GetInstanceDiskUsage(const std::string& path, uid_t uid) } if (!QuotasSupported(devicePath)) { - LOG_ERR() << "Quotas are not supported on device" << Log::Field("devicePath", devicePath.c_str()); + LOG_WRN() << "Quotas are not supported on device" << Log::Field("devicePath", devicePath.c_str()); return 0; } @@ -217,7 +217,7 @@ size_t Monitoring::GetInstanceDiskUsage(const std::string& path, uid_t uid) AOS_ERROR_THROW(ErrorEnum::eFailed, "failed to get quota"); } - return static_cast(quota.dqb_curspace); + return static_cast(quota.dqb_curspace * 1024); } }; // namespace aos::sm::launcher diff --git a/src/sm/smclient/smclient.cpp b/src/sm/smclient/smclient.cpp index 388aa062..46f8d3b8 100644 --- a/src/sm/smclient/smclient.cpp +++ b/src/sm/smclient/smclient.cpp @@ -417,46 +417,32 @@ void SMClient::HandleIncomingMessages() smproto::SMIncomingMessages incomingMsg; while (mStream->Read(&incomingMsg)) { + Error err; + if (incomingMsg.has_get_node_config_status()) { - if (auto err = ProcessGetNodeConfigStatus(); !err.IsNone()) { - LOG_ERR() << "Failed to process get node config status: err=" << err; - } + err = ProcessGetNodeConfigStatus(); } else if (incomingMsg.has_check_node_config()) { - if (auto err = ProcessCheckNodeConfig(incomingMsg.check_node_config()); !err.IsNone()) { - LOG_ERR() << "Failed to process check node config: err=" << err; - } + err = ProcessCheckNodeConfig(incomingMsg.check_node_config()); } else if (incomingMsg.has_set_node_config()) { - if (auto err = ProcessSetNodeConfig(incomingMsg.set_node_config()); !err.IsNone()) { - LOG_ERR() << "Failed to process set node config: err=" << err; - } + err = ProcessSetNodeConfig(incomingMsg.set_node_config()); } else if (incomingMsg.has_update_instances()) { - if (auto err = ProcessUpdateInstances(incomingMsg.update_instances()); !err.IsNone()) { - LOG_ERR() << "Failed to process update instances: err=" << err; - } + err = ProcessUpdateInstances(incomingMsg.update_instances()); } else if (incomingMsg.has_system_log_request()) { - if (auto err = ProcessSystemLogRequest(incomingMsg.system_log_request()); !err.IsNone()) { - LOG_ERR() << "Failed to process system log request: err=" << err; - } + err = ProcessSystemLogRequest(incomingMsg.system_log_request()); } else if (incomingMsg.has_instance_log_request()) { - if (auto err = ProcessInstanceLogRequest(incomingMsg.instance_log_request()); !err.IsNone()) { - LOG_ERR() << "Failed to process instance log request: err=" << err; - } + err = ProcessInstanceLogRequest(incomingMsg.instance_log_request()); } else if (incomingMsg.has_instance_crash_log_request()) { - if (auto err = ProcessInstanceCrashLogRequest(incomingMsg.instance_crash_log_request()); !err.IsNone()) { - LOG_ERR() << "Failed to process instance crash log request: err=" << err; - } + err = ProcessInstanceCrashLogRequest(incomingMsg.instance_crash_log_request()); } else if (incomingMsg.has_get_average_monitoring()) { - if (auto err = ProcessGetAverageMonitoring(); !err.IsNone()) { - LOG_ERR() << "Failed to process get average monitoring: err=" << err; - } + err = ProcessGetAverageMonitoring(); } else if (incomingMsg.has_connection_status()) { - if (auto err = ProcessConnectionStatus(incomingMsg.connection_status()); !err.IsNone()) { - LOG_ERR() << "Failed to process connection status: err=" << err; - } + err = ProcessConnectionStatus(incomingMsg.connection_status()); } else if (incomingMsg.has_update_networks()) { - if (auto err = ProcessUpdateNetworks(incomingMsg.update_networks()); !err.IsNone()) { - LOG_ERR() << "Failed to process update networks: err=" << err; - } + err = ProcessUpdateNetworks(incomingMsg.update_networks()); + } + + if (!err.IsNone()) { + LOG_ERR() << "Failed to process incoming message" << Log::Field(err); } } }