diff --git a/src/cm/database/database.hpp b/src/cm/database/database.hpp index f075a2503..70c37186c 100644 --- a/src/cm/database/database.hpp +++ b/src/cm/database/database.hpp @@ -38,7 +38,7 @@ class Database : public DatabaseItf, public common::database::Database, public n /** * Destructor. */ - ~Database(); + ~Database() override; /** * Initializes database. diff --git a/src/cm/smcontroller/smcontroller.cpp b/src/cm/smcontroller/smcontroller.cpp index 22399626d..7c661a5f2 100644 --- a/src/cm/smcontroller/smcontroller.cpp +++ b/src/cm/smcontroller/smcontroller.cpp @@ -279,25 +279,29 @@ grpc::Status SMController::RegisterSM(grpc::ServerContext* return grpc::Status::OK; } -grpc::Status SMController::GetBlobsInfos(grpc::ServerContext*, const servicemanager::v5::BlobsInfosRequest* request, - servicemanager::v5::BlobsInfos* response) +grpc::Status SMController::GetBlobsInfo( + grpc::ServerContext*, const servicemanager::v5::BlobsInfoRequest* request, servicemanager::v5::BlobInfo* response) { - LOG_DBG() << "Get blobs info request received" << Log::Field("digestsCount", request->digests_size()); + LOG_DBG() << "Get blob info request received" << Log::Field("digest", request->digest().c_str()); auto blobInfo = std::make_unique(); - for (int i = 0; i < request->digests_size(); ++i) { - if (auto err = mBlobInfoProvider->GetBlobInfo(request->digests(i).c_str(), *blobInfo); !err.IsNone()) { - return grpc::Status(grpc::StatusCode::INTERNAL, err.Message()); - } + auto err = mBlobInfoProvider->GetBlobInfo(request->digest().c_str(), *blobInfo); + if (err.IsNone() && blobInfo->mURLs.IsEmpty()) { + err = Error(ErrorEnum::eNotFound, "blob has no URLs"); + } - if (blobInfo->mURLs.IsEmpty()) { - return grpc::Status(grpc::StatusCode::INTERNAL, "blob has no URLs"); - } + // The error is returned in the response, so SM gets its code, e.g. integrity error of the CM copy. + if (!err.IsNone()) { + LOG_ERR() << "Failed to get blob info" << Log::Field("digest", request->digest().c_str()) << Log::Field(err); - response->add_urls(blobInfo->mURLs[0].CStr()); + common::pbconvert::SetErrorInfo(err, *response); + + return grpc::Status::OK; } + common::pbconvert::ConvertToProto(*blobInfo, *response); + return grpc::Status::OK; } diff --git a/src/cm/smcontroller/smcontroller.hpp b/src/cm/smcontroller/smcontroller.hpp index 281fcb138..5a5d61b7e 100644 --- a/src/cm/smcontroller/smcontroller.hpp +++ b/src/cm/smcontroller/smcontroller.hpp @@ -190,8 +190,8 @@ class SMController : public SMControllerItf, grpc::ServerReaderWriter* stream) override; - grpc::Status GetBlobsInfos(grpc::ServerContext* context, const servicemanager::v5::BlobsInfosRequest* request, - servicemanager::v5::BlobsInfos* response) override; + grpc::Status GetBlobsInfo(grpc::ServerContext* context, const servicemanager::v5::BlobsInfoRequest* request, + servicemanager::v5::BlobInfo* response) override; // // NetworkService::Service GRPC service methods diff --git a/src/cm/smcontroller/tests/smcontroller.cpp b/src/cm/smcontroller/tests/smcontroller.cpp index d62dcc518..160b2e065 100644 --- a/src/cm/smcontroller/tests/smcontroller.cpp +++ b/src/cm/smcontroller/tests/smcontroller.cpp @@ -9,6 +9,7 @@ #include #include +#include #include "stubs/alertsreceiverstub.hpp" #include "stubs/blobinfoproviderstub.hpp" @@ -842,7 +843,7 @@ TEST_F(SMControllerTest, OnCertKeyChanged) EXPECT_TRUE(err.IsNone()) << err.Message(); } -TEST_F(SMControllerTest, GetBlobsInfos) +TEST_F(SMControllerTest, GetBlobsInfo) { const std::string digest1 = "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; const std::string digest2 = "sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"; @@ -866,14 +867,23 @@ TEST_F(SMControllerTest, GetBlobsInfos) err = mSMInfoReceiver.WaitSMInfo(cMainNodeID); ASSERT_TRUE(err.IsNone()) << err.Message(); - // 4) Call GetBlobsInfos - servicemanager::v5::BlobsInfos responseBlobsInfos; - std::vector digests = {digest2, digest1}; - ASSERT_TRUE(client.GetBlobsInfos(digests, responseBlobsInfos).IsNone()); + // 4) Call GetBlobsInfo + servicemanager::v5::BlobInfo blobInfo; - ASSERT_EQ(responseBlobsInfos.urls_size(), 2); - EXPECT_EQ(responseBlobsInfos.urls(0), url2); - EXPECT_EQ(responseBlobsInfos.urls(1), url1); + ASSERT_TRUE(client.GetBlobsInfo(digest1, blobInfo).IsNone()); + + EXPECT_FALSE(blobInfo.has_error()); + ASSERT_EQ(blobInfo.urls_size(), 2); + EXPECT_EQ(blobInfo.urls(0), url1); + EXPECT_EQ(blobInfo.urls(1), "https://backup.example.com/blob1.tar"); + + blobInfo.Clear(); + + ASSERT_TRUE(client.GetBlobsInfo(digest2, blobInfo).IsNone()); + + EXPECT_FALSE(blobInfo.has_error()); + ASSERT_EQ(blobInfo.urls_size(), 1); + EXPECT_EQ(blobInfo.urls(0), url2); // 5) Stop client err = client.Stop(); @@ -884,7 +894,7 @@ TEST_F(SMControllerTest, GetBlobsInfos) EXPECT_TRUE(err.IsNone()) << err.Message(); } -TEST_F(SMControllerTest, GetBlobsInfosFails) +TEST_F(SMControllerTest, GetBlobsInfoFails) { const std::string knownDigest = "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; const std::string noURLsDigest = "sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"; @@ -904,15 +914,28 @@ TEST_F(SMControllerTest, GetBlobsInfosFails) err = mSMInfoReceiver.WaitSMInfo(cMainNodeID); ASSERT_TRUE(err.IsNone()) << err.Message(); - servicemanager::v5::BlobsInfos responseBlobsInfos; + // The provider error is returned in the response with its code. + servicemanager::v5::BlobInfo blobInfo; + + ASSERT_TRUE(client.GetBlobsInfo(unknownDigest, blobInfo).IsNone()); + + ASSERT_TRUE(blobInfo.has_error()); + EXPECT_TRUE(common::pbconvert::ConvertFromProto(blobInfo.error()).Is(ErrorEnum::eNotFound)); + EXPECT_EQ(blobInfo.urls_size(), 0); + + blobInfo.Clear(); + + ASSERT_TRUE(client.GetBlobsInfo(noURLsDigest, blobInfo).IsNone()); + + ASSERT_TRUE(blobInfo.has_error()); + EXPECT_NE(blobInfo.error().message().find("blob has no URLs"), std::string::npos) << blobInfo.error().message(); - EXPECT_FALSE(client.GetBlobsInfos({knownDigest, unknownDigest}, responseBlobsInfos).IsNone()); + blobInfo.Clear(); - responseBlobsInfos.Clear(); + ASSERT_TRUE(client.GetBlobsInfo(knownDigest, blobInfo).IsNone()); - err = client.GetBlobsInfos({noURLsDigest}, responseBlobsInfos); - EXPECT_FALSE(err.IsNone()); - EXPECT_NE(std::string(err.Message()).find("blob has no URLs"), std::string::npos) << err.Message(); + EXPECT_FALSE(blobInfo.has_error()); + EXPECT_EQ(blobInfo.urls_size(), 1); err = client.Stop(); ASSERT_TRUE(err.IsNone()) << err.Message(); diff --git a/src/cm/smcontroller/tests/stubs/smclientstub.hpp b/src/cm/smcontroller/tests/stubs/smclientstub.hpp index a45ae5164..ddadaceb7 100644 --- a/src/cm/smcontroller/tests/stubs/smclientstub.hpp +++ b/src/cm/smcontroller/tests/stubs/smclientstub.hpp @@ -371,7 +371,7 @@ class SMClientStub { return ErrorEnum::eNone; } - Error GetBlobsInfos(const std::vector& digests, servicemanager::v5::BlobsInfos& blobsInfos) + Error GetBlobsInfo(const std::string& digest, servicemanager::v5::BlobInfo& blobInfo) { std::lock_guard lock {mMutex}; @@ -379,13 +379,12 @@ class SMClientStub { return AOS_ERROR_WRAP(Error(ErrorEnum::eFailed, "stub not available")); } - servicemanager::v5::BlobsInfosRequest request; - for (const auto& digest : digests) { - request.add_digests(digest); - } + servicemanager::v5::BlobsInfoRequest request; + + request.set_digest(digest); grpc::ClientContext context; - auto status = mStub->GetBlobsInfos(&context, request, &blobsInfos); + auto status = mStub->GetBlobsInfo(&context, request, &blobInfo); if (!status.ok()) { return AOS_ERROR_WRAP(Error(ErrorEnum::eFailed, status.error_message().c_str())); diff --git a/src/common/fileserver/fileserver.cpp b/src/common/fileserver/fileserver.cpp index ff95ab849..4475e3c24 100644 --- a/src/common/fileserver/fileserver.cpp +++ b/src/common/fileserver/fileserver.cpp @@ -287,7 +287,7 @@ bool Fileserver::FileRequestHandler::ResolvePath(const std::string& target, fs:: Fileserver::FileRequestHandler::FDPtr Fileserver::FileRequestHandler::OpenFile( const std::string& path, struct stat& st, Poco::Net::HTTPServerResponse& response) { - FDPtr fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK)); + FDPtr fd(FDHandle(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NONBLOCK))); if (!fd) { auto err = errno; diff --git a/src/common/fileserver/fileserver.hpp b/src/common/fileserver/fileserver.hpp index 5c1baef39..9186a74c9 100644 --- a/src/common/fileserver/fileserver.hpp +++ b/src/common/fileserver/fileserver.hpp @@ -173,8 +173,10 @@ class Fileserver : public cm::fileserver::FileServerItf, public aos::iamclient:: struct FDHandle { int mFD = -1; + // Implicit conversion from nullptr is required by unique_ptr pointer type. + // cppcheck-suppress noExplicitConstructor FDHandle(std::nullptr_t = nullptr) { } - FDHandle(int fd) + explicit FDHandle(int fd) : mFD(fd) { } diff --git a/src/common/pbconvert/sm.cpp b/src/common/pbconvert/sm.cpp index 7c284a61c..f49eac3c8 100644 --- a/src/common/pbconvert/sm.cpp +++ b/src/common/pbconvert/sm.cpp @@ -1309,4 +1309,42 @@ Error ConvertFromProto(const servicemanager::v5::InstanceNetworkStateInfo& src, return ErrorEnum::eNone; } +void ConvertToProto(const BlobInfo& src, servicemanager::v5::BlobInfo& dst) +{ + for (const auto& url : src.mURLs) { + dst.add_urls(url.CStr()); + } + + dst.set_sha256(std::string(reinterpret_cast(src.mSHA256.Get()), src.mSHA256.Size())); + dst.set_size(src.mSize); +} + +Error ConvertFromProto(const servicemanager::v5::BlobInfo& src, const String& digest, BlobInfo& dst) +{ + if (auto err = dst.mDigest.Assign(digest); !err.IsNone()) { + return AOS_ERROR_WRAP(err); + } + + // The proto doesn't carry the decrypt and sign info, so the fields of a reused blob info are reset. + dst.mURLs.Clear(); + dst.mDecryptInfo.Reset(); + dst.mSignInfo.Reset(); + + for (const auto& url : src.urls()) { + if (auto err = dst.mURLs.PushBack(url.c_str()); !err.IsNone()) { + return AOS_ERROR_WRAP(err); + } + } + + if (auto err = dst.mSHA256.Assign( + Array(reinterpret_cast(src.sha256().data()), src.sha256().size())); + !err.IsNone()) { + return AOS_ERROR_WRAP(err); + } + + dst.mSize = src.size(); + + return ErrorEnum::eNone; +} + } // namespace aos::common::pbconvert diff --git a/src/common/pbconvert/sm.hpp b/src/common/pbconvert/sm.hpp index 5984d8dcd..2389a6f60 100644 --- a/src/common/pbconvert/sm.hpp +++ b/src/common/pbconvert/sm.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -344,6 +345,24 @@ Error ConvertToProto(const InstanceNetworkStateInfo& src, servicemanager::v5::In */ Error ConvertFromProto(const servicemanager::v5::InstanceNetworkStateInfo& src, InstanceNetworkStateInfo& dst); +/** + * Converts Aos blob info to grpc BlobInfo. + * + * @param src Aos blob info. + * @param[out] dst grpc blob info. + */ +void ConvertToProto(const BlobInfo& src, servicemanager::v5::BlobInfo& dst); + +/** + * Converts grpc BlobInfo to Aos. + * + * @param src grpc blob info. + * @param digest blob digest. + * @param[out] dst Aos blob info. + * @return Error. + */ +Error ConvertFromProto(const servicemanager::v5::BlobInfo& src, const String& digest, BlobInfo& dst); + } // namespace aos::common::pbconvert #endif diff --git a/src/common/pbconvert/tests/sm.cpp b/src/common/pbconvert/tests/sm.cpp index e51a1994e..767893df2 100644 --- a/src/common/pbconvert/tests/sm.cpp +++ b/src/common/pbconvert/tests/sm.cpp @@ -805,4 +805,57 @@ TEST_F(PBConvertSMTest, ConvertInstanceNetworkParamsToAllocateInstanceNetworkRes EXPECT_EQ(result.dns_servers_size(), 0); } +TEST_F(PBConvertSMTest, ConvertBlobInfoToProto) +{ + const uint8_t cSHA256[] = {0x01, 0x02, 0x03, 0x04}; + + auto blobInfo = std::make_unique(); + + blobInfo->mDigest = "sha256:blob"; + blobInfo->mSize = 1024; + + ASSERT_TRUE(blobInfo->mURLs.PushBack("https://example.com/blob1").IsNone()); + ASSERT_TRUE(blobInfo->mURLs.PushBack("https://example.com/blob2").IsNone()); + ASSERT_TRUE(blobInfo->mSHA256.Assign(Array(cSHA256, sizeof(cSHA256))).IsNone()); + + servicemanager::v5::BlobInfo result; + + ConvertToProto(*blobInfo, result); + + ASSERT_EQ(result.urls_size(), 2); + EXPECT_EQ(result.urls(0), "https://example.com/blob1"); + EXPECT_EQ(result.urls(1), "https://example.com/blob2"); + EXPECT_EQ(result.sha256(), std::string("\x01\x02\x03\x04")); + EXPECT_EQ(result.size(), 1024); + EXPECT_FALSE(result.has_error()); +} + +TEST_F(PBConvertSMTest, ConvertBlobInfoFromProto) +{ + const uint8_t cSHA256[] = {0x01, 0x02, 0x03, 0x04}; + + servicemanager::v5::BlobInfo grpcData; + + grpcData.add_urls("https://example.com/blob1"); + grpcData.add_urls("https://example.com/blob2"); + grpcData.set_sha256(std::string("\x01\x02\x03\x04")); + grpcData.set_size(1024); + + auto blobInfo = std::make_unique(); + + ASSERT_TRUE(blobInfo->mURLs.PushBack("https://example.com/stale").IsNone()); + + auto err = ConvertFromProto(grpcData, "sha256:blob", *blobInfo); + ASSERT_TRUE(err.IsNone()) << err.Message(); + + EXPECT_EQ(blobInfo->mDigest, "sha256:blob"); + ASSERT_EQ(blobInfo->mURLs.Size(), 2); + EXPECT_EQ(blobInfo->mURLs[0], "https://example.com/blob1"); + EXPECT_EQ(blobInfo->mURLs[1], "https://example.com/blob2"); + EXPECT_EQ(blobInfo->mSHA256, Array(cSHA256, sizeof(cSHA256))); + EXPECT_EQ(blobInfo->mSize, 1024); + EXPECT_FALSE(blobInfo->mDecryptInfo.HasValue()); + EXPECT_FALSE(blobInfo->mSignInfo.HasValue()); +} + } // namespace aos::common::pbconvert diff --git a/src/sm/app/aoscore.cpp b/src/sm/app/aoscore.cpp index 636a50cf8..491e65f55 100644 --- a/src/sm/app/aoscore.cpp +++ b/src/sm/app/aoscore.cpp @@ -124,8 +124,8 @@ void AosCore::Init(const std::string& configFile) // Initialize images space allocator - err = mImagesSpaceAllocator.Init( - mAllocator, mConfig.mImageManager.mImagePath, mPlatformFS, mConfig.mImageManager.mPartLimit, &mImageManager); + err = mImagesSpaceAllocator.Init(mAllocator, mConfig.mImageManager.mImagePath, mPlatformFS, + mConfig.mImageManager.mPartLimit, &mImageManager.GetItemRemover()); AOS_ERROR_CHECK_AND_THROW(err, "can't initialize images space allocator"); // Initialize downloader @@ -139,14 +139,14 @@ void AosCore::Init(const std::string& configFile) // Initialize image manager - err = mImageManager.Init(mAllocator, mConfig.mImageManager, mSMClient, mImagesSpaceAllocator, mDownloader, - mFileInfoProvider, mOCISpec, mImageHandler, mDatabase); + err = mImageManager.Init(mConfig.mImageManager, mSMClient, mDatabase, mImagesSpaceAllocator, mDownloader, + mImageHandler, mFileInfoProvider, mOCISpec, mPlatformFS, mAllocator); AOS_ERROR_CHECK_AND_THROW(err, "can't initialize image manager"); // Initialize launcher - err = mLauncher.Init(mAllocator, *runtimes, mImageManager, mSMClient, mDatabase, mOCISpec, mImageManager, mSMClient, - mNetworkManager, mInstanceIDProvider, mResourceManager); + err = mLauncher.Init(mAllocator, *runtimes, mImageManager, mImageManager, mSMClient, mDatabase, mOCISpec, + mImageManager, mSMClient, mNetworkManager, mInstanceIDProvider, mResourceManager); AOS_ERROR_CHECK_AND_THROW(err, "can't initialize launcher"); // Initialize node config handler diff --git a/src/sm/config/config.cpp b/src/sm/config/config.cpp index 4d94b2696..1dc76440b 100644 --- a/src/sm/config/config.cpp +++ b/src/sm/config/config.cpp @@ -62,7 +62,7 @@ void ParseSMClientConfig(const common::utils::CaseInsensitiveObjectWrapper& obje }; void ParseImageManagerConfig(const common::utils::CaseInsensitiveObjectWrapper& object, const std::string& workingDir, - imagemanager::Config& config) + aos::common::imagemanager::Config& config) { Error err; @@ -72,7 +72,7 @@ void ParseImageManagerConfig(const common::utils::CaseInsensitiveObjectWrapper& config.mPartLimit = object.GetValue("imagesPartLimit", 0); - Tie(config.mUpdateItemTTL, err) + Tie(config.mItemCacheTTL, err) = common::utils::ParseDuration(object.GetValue("updateItemTtl", cDefaultUpdateItemTTL)); AOS_ERROR_CHECK_AND_THROW(err, "error parsing updateItemTtl tag"); diff --git a/src/sm/config/config.hpp b/src/sm/config/config.hpp index 17f3cb843..ce73a7900 100644 --- a/src/sm/config/config.hpp +++ b/src/sm/config/config.hpp @@ -12,10 +12,10 @@ #include +#include #include #include #include -#include #include #include @@ -41,7 +41,7 @@ struct Config { common::config::JournalAlerts mJournalAlerts; common::config::Migration mMigration; common::iamclient::Config mIAMClientConfig; - imagemanager::Config mImageManager; + common::imagemanager::Config mImageManager; launcher::Config mLauncher; logging::Config mLogging; monitoring::Config mMonitoring; diff --git a/src/sm/config/tests/config.cpp b/src/sm/config/tests/config.cpp index e18e3ab2f..71a7b0c7b 100644 --- a/src/sm/config/tests/config.cpp +++ b/src/sm/config/tests/config.cpp @@ -156,7 +156,7 @@ TEST_F(ConfigTest, ParseConfig) EXPECT_EQ(config->mImageManager.mImagePath, "/path/to/images"); EXPECT_EQ(config->mImageManager.mPartLimit, 50); - EXPECT_EQ(config->mImageManager.mUpdateItemTTL, 15 * 24 * aos::Time::cHours); + EXPECT_EQ(config->mImageManager.mItemCacheTTL, 15 * 24 * aos::Time::cHours); EXPECT_EQ(config->mImageManager.mRemoveOutdatedPeriod, 12 * aos::Time::cHours); EXPECT_EQ(config->mLauncher.mRuntimes.size(), 3); diff --git a/src/sm/database/CMakeLists.txt b/src/sm/database/CMakeLists.txt index 5e9b39dbe..d77abb290 100644 --- a/src/sm/database/CMakeLists.txt +++ b/src/sm/database/CMakeLists.txt @@ -16,7 +16,9 @@ set(SOURCES database.cpp) # Libraries # ###################################################################################################################### -set(LIBRARIES aos::sm::config aos::common::utils aos::common::migration Poco::DataSQLite Poco::JSON) +set(LIBRARIES aos::sm::config aos::common::database aos::common::utils aos::common::migration Poco::DataSQLite + Poco::JSON +) # ###################################################################################################################### # Target diff --git a/src/sm/database/database.cpp b/src/sm/database/database.cpp index 4131d33e4..69bcbba02 100644 --- a/src/sm/database/database.cpp +++ b/src/sm/database/database.cpp @@ -449,152 +449,22 @@ Error Database::Init(const std::string& workDir, const common::config::Migration * sm::imagemanager::StorageItf implementation **********************************************************************************************************************/ -Error Database::AddUpdateItem(const imagemanager::UpdateItemData& updateItem) +RetWithError Database::IsLayerUsed(const String& diffID) { - std::lock_guard lock {mMutex}; - - LOG_DBG() << "Add update item" << Log::Field("id", updateItem.mID) << Log::Field("type", updateItem.mType) - << Log::Field("version", updateItem.mVersion) << Log::Field("state", updateItem.mState); - - try { - ItemDataRow row; - - FromAos(updateItem, row); - - *mSession - << "INSERT INTO items (itemID, type, version, manifestDigest, state, timestamp) VALUES (?, ?, ?, ?, ?, ?);", - bind(row), now; - - return ErrorEnum::eNone; - } catch (const std::exception& e) { - return AOS_ERROR_WRAP(common::utils::ToAosError(e)); - } -} - -Error Database::UpdateUpdateItem(const imagemanager::UpdateItemData& updateItem) -{ - std::lock_guard lock {mMutex}; - - LOG_DBG() << "Update update item" << Log::Field("id", updateItem.mID) << Log::Field("type", updateItem.mType) - << Log::Field("version", updateItem.mVersion) << Log::Field("state", updateItem.mState); - - try { - Poco::Data::Statement statement {*mSession}; - - statement << "UPDATE items SET manifestDigest = ?, state = ?, timestamp = ? WHERE itemID = ? AND type = ? AND " - "version = ?;", - bind(updateItem.mManifestDigest.CStr()), bind(updateItem.mState.ToString().CStr()), - bind(updateItem.mTimestamp.UnixNano()), bind(updateItem.mID.CStr()), - bind(updateItem.mType.ToString().CStr()), bind(updateItem.mVersion.CStr()); - - if (statement.execute() != 1) { - return ErrorEnum::eNotFound; - } - - return ErrorEnum::eNone; - } catch (const std::exception& e) { - return AOS_ERROR_WRAP(common::utils::ToAosError(e)); - } -} - -Error Database::RemoveUpdateItem(const String& itemID, const String& version) -{ - std::lock_guard lock {mMutex}; - - LOG_DBG() << "Remove update item" << Log::Field("id", itemID) << Log::Field("version", version); - - try { - Poco::Data::Statement statement {*mSession}; - - statement << "DELETE FROM items WHERE itemID = ? AND version = ?;", bind(itemID.CStr()), bind(version.CStr()); - - if (statement.execute() == 0) { - return AOS_ERROR_WRAP(ErrorEnum::eNotFound); - } - - return ErrorEnum::eNone; - } catch (const std::exception& e) { - return AOS_ERROR_WRAP(common::utils::ToAosError(e)); - } -} - -Error Database::GetUpdateItem(const String& itemID, Array& itemData) -{ - std::lock_guard lock {mMutex}; - - LOG_DBG() << "Get update item" << Log::Field("id", itemID); + LOG_DBG() << "Check if layer is used" << Log::Field("diffID", diffID); - try { - std::vector rows; - Poco::Data::Statement statement {*mSession}; - - statement << "SELECT * FROM items WHERE itemID = ?;", bind(itemID.CStr()), into(rows); - - if (statement.execute() == 0) { - return ErrorEnum::eNotFound; - } - - for (const auto& row : rows) { - imagemanager::UpdateItemData updateItem; - - ToAos(row, updateItem); - - if (auto err = itemData.PushBack(updateItem); !err.IsNone()) { - return AOS_ERROR_WRAP(Error(err, "db items count exceeds application limit")); - } - } - - return ErrorEnum::eNone; - } catch (const std::exception& e) { - return AOS_ERROR_WRAP(common::utils::ToAosError(e)); - } -} - -Error Database::GetAllUpdateItems(Array& itemsData) -{ - std::lock_guard lock {mMutex}; - - LOG_DBG() << "Get all update items"; - - try { - std::vector rows; - Poco::Data::Statement statement {*mSession}; - - statement << "SELECT * FROM items;", into(rows); - - statement.execute(); - - for (const auto& row : rows) { - imagemanager::UpdateItemData updateItem; - - ToAos(row, updateItem); - - if (auto err = itemsData.PushBack(updateItem); !err.IsNone()) { - return AOS_ERROR_WRAP(Error(err, "db items count exceeds application limit")); - } - } - - return ErrorEnum::eNone; - } catch (const std::exception& e) { - return AOS_ERROR_WRAP(common::utils::ToAosError(e)); - } -} - -RetWithError Database::GetUpdateItemsCount() -{ std::lock_guard lock {mMutex}; - LOG_DBG() << "Get update items count"; - try { - Poco::Data::Statement statement {*mSession}; - size_t count; + int used = 0; - statement << "SELECT COUNT(*) FROM items;", into(count), now; + *mSession << "SELECT EXISTS (SELECT 1 FROM imagemanager_blobs b JOIN imagemanager_items i " + "ON b.itemID = i.itemID AND b.version = i.version WHERE b.isLayer = 1 AND b.diffID = ?);", + bind(diffID.CStr()), into(used), now; - return {count, ErrorEnum::eNone}; + return {used != 0, ErrorEnum::eNone}; } catch (const std::exception& e) { - return {0, AOS_ERROR_WRAP(common::utils::ToAosError(e))}; + return {false, AOS_ERROR_WRAP(common::utils::ToAosError(e))}; } } @@ -1207,36 +1077,6 @@ void Database::CreateTables() now; } -void Database::FromAos(const imagemanager::UpdateItemData& src, ItemDataRow& dst) -{ - dst.set(src.mID.CStr()); - dst.set(src.mType.ToString().CStr()); - dst.set(src.mVersion.CStr()); - dst.set(src.mManifestDigest.CStr()); - dst.set(src.mState.ToString().CStr()); - dst.set(src.mTimestamp.UnixNano()); -} - -void Database::ToAos(const ItemDataRow& src, imagemanager::UpdateItemData& dst) -{ - auto err = dst.mID.Assign(src.get().c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "failed to assign item ID"); - - err = dst.mType.FromString(src.get().c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "failed to parse item type"); - - err = dst.mVersion.Assign(src.get().c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "failed to assign item version"); - - err = dst.mManifestDigest.Assign(src.get().c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "failed to assign manifest digest"); - - err = dst.mState.FromString(src.get().c_str()); - AOS_ERROR_CHECK_AND_THROW(err, "failed to parse item state"); - - dst.mTimestamp = ConvertTimestamp(src.get()); -} - void Database::FromAos(const InstanceInfo& src, InstanceInfoRow& dst) { dst.set(src.mItemID.CStr()); diff --git a/src/sm/database/database.hpp b/src/sm/database/database.hpp index 50a2def18..714df72b0 100644 --- a/src/sm/database/database.hpp +++ b/src/sm/database/database.hpp @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -24,7 +25,10 @@ namespace aos::sm::database { -class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::launcher::runtimes::StorageItf { +class Database : public DatabaseItf, + public common::database::Database, + public sm::alerts::StorageItf, + public sm::launcher::runtimes::StorageItf { public: /** * Creates database instance. @@ -34,7 +38,7 @@ class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::l /** * Destructor. */ - ~Database(); + ~Database() override; /** * Initializes certificate info storage. @@ -48,53 +52,13 @@ class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::l // sm::imagemanager::StorageItf interface /** - * Adds update item to storage. + * Checks if layer is referenced by any existing deployable item, regardless of the item state. Blob references + * left without an item are ignored. * - * @param updateItem update item to add. - * @return Error. - */ - Error AddUpdateItem(const imagemanager::UpdateItemData& updateItem) override; - - /** - * Updates update item in storage. - * - * @param updateItem update item to update. - * @return Error. - */ - Error UpdateUpdateItem(const imagemanager::UpdateItemData& updateItem) override; - - /** - * Removes previously stored update item. - * - * @param itemID update item ID to remove. - * @param version update item version. - * @return Error. - */ - Error RemoveUpdateItem(const String& itemID, const String& version) override; - - /** - * Returns update item versions by item ID. - * - * @param itemID update item ID. - * @param[out] itemData array to store update item data. - * @return Error. - */ - Error GetUpdateItem(const String& itemID, Array& itemData) override; - - /** - * Returns all update items. - * - * @param itemsData[out] array to store update items data. - * @return Error. + * @param diffID layer diff ID. + * @return RetWithError. */ - Error GetAllUpdateItems(Array& itemsData) override; - - /** - * Returns count of stored update items. - * - * @return RetWithError. - */ - RetWithError GetUpdateItemsCount() override; + RetWithError IsLayerUsed(const String& diffID) override; // sm::launcher::StorageItf interface @@ -288,21 +252,9 @@ class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::l const String& runtimeID, Array& instances) const override; private: - static constexpr int sVersion = 6; + static constexpr int sVersion = 7; static constexpr auto cDBFileName = "servicemanager.db"; - // Item data columns - enum class ItemDataColumns : int { - eItemID = 0, - eType, - eVersion, - eManifestDigest, - eState, - eTimestamp, - }; - - using ItemDataRow = Poco::Tuple; - // Instance info columns enum class InstanceInfoColumns : int { eItemID = 0, @@ -376,9 +328,6 @@ class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::l // FromAos/ToAos conversion methods - static void FromAos(const imagemanager::UpdateItemData& src, ItemDataRow& dst); - static void ToAos(const ItemDataRow& src, imagemanager::UpdateItemData& dst); - static void FromAos(const InstanceInfo& src, InstanceInfoRow& dst); static void ToAos(const InstanceInfoRow& src, InstanceInfo& dst); @@ -391,9 +340,7 @@ class Database : public DatabaseItf, public sm::alerts::StorageItf, public sm::l static void FromAos(const sm::launcher::runtimes::RuntimeInstanceData& src, RuntimeInstanceRow& dst); static void ToAos(const RuntimeInstanceRow& src, sm::launcher::runtimes::RuntimeInstanceData& dst); - mutable std::unique_ptr mSession; - std::optional mMigration; - mutable std::mutex mMutex; + std::optional mMigration; }; } // namespace aos::sm::database diff --git a/src/sm/database/migration/7_update.down.sql b/src/sm/database/migration/7_update.down.sql new file mode 100644 index 000000000..9caaf874c --- /dev/null +++ b/src/sm/database/migration/7_update.down.sql @@ -0,0 +1,16 @@ +BEGIN TRANSACTION; + +DROP TABLE IF EXISTS imagemanager_blobs; +DROP TABLE IF EXISTS imagemanager_items; + +CREATE TABLE IF NOT EXISTS items ( + itemID TEXT, + type TEXT, + version TEXT, + manifestDigest TEXT, + state TEXT, + timestamp INTEGER, + PRIMARY KEY(itemID, type, version) +); + +COMMIT; diff --git a/src/sm/database/migration/7_update.up.sql b/src/sm/database/migration/7_update.up.sql new file mode 100644 index 000000000..b5afddef4 --- /dev/null +++ b/src/sm/database/migration/7_update.up.sql @@ -0,0 +1,33 @@ +BEGIN TRANSACTION; + +DROP TABLE IF EXISTS items; + +CREATE TABLE IF NOT EXISTS imagemanager_items ( + itemID TEXT, + type TEXT, + version TEXT, + preinstalled INTEGER, + state TEXT, + errorAosCode INTEGER, + errorSysCode INTEGER, + errorMessage TEXT, + rootDigest TEXT, + timestamp INTEGER, + PRIMARY KEY (itemID, version) +); + +CREATE TABLE IF NOT EXISTS imagemanager_blobs ( + itemID TEXT, + version TEXT, + digest TEXT, + mediaType TEXT, + size INTEGER, + isLayer INTEGER, + diffID TEXT, + PRIMARY KEY (itemID, version, digest) +); + +CREATE INDEX IF NOT EXISTS imagemanager_blobs_digest ON imagemanager_blobs(digest); +CREATE INDEX IF NOT EXISTS imagemanager_blobs_diffID ON imagemanager_blobs(diffID); + +COMMIT; diff --git a/src/sm/database/tests/database.cpp b/src/sm/database/tests/database.cpp index 5ee455ba5..1bfcbee3e 100644 --- a/src/sm/database/tests/database.cpp +++ b/src/sm/database/tests/database.cpp @@ -57,21 +57,34 @@ aos::InstanceInfo CreateInstanceInfo( return info; } -aos::sm::imagemanager::UpdateItemData CreateUpdateItemData(const aos::String& id, aos::UpdateItemType type, - const aos::String& version, const aos::String& manifestDigest, aos::ItemState state, aos::Time timestamp) +aos::common::imagemanager::DeployableItemInfo CreateDeployableItem(const char* itemID, const char* version) { - aos::sm::imagemanager::UpdateItemData item; + aos::common::imagemanager::DeployableItemInfo item; - item.mID = id; - item.mType = type; - item.mVersion = version; - item.mManifestDigest = manifestDigest; - item.mState = state; - item.mTimestamp = timestamp; + item.mItemID = itemID; + item.mType = aos::UpdateItemTypeEnum::eService; + item.mVersion = version; + item.mState = aos::ItemStateEnum::eInstalled; + item.mRootDigest = "sha256:root"; + item.mTimestamp = aos::Time::Now(); return item; } +aos::common::imagemanager::ItemBlobInfo CreateItemBlob(const char* digest, bool isLayer, const char* diffID) +{ + aos::common::imagemanager::ItemBlobInfo blob; + + blob.mMediaType + = isLayer ? "application/vnd.oci.image.layer.v1.tar+gzip" : "application/vnd.oci.image.manifest.v1+json"; + blob.mDigest = digest; + blob.mSize = 1024; + blob.mIsLayer = isLayer; + blob.mDiffID = diffID; + + return blob; +} + aos::sm::launcher::runtimes::RuntimeInstanceData CreateRuntimeInstance(const std::string& runtimeID, const std::string& version, aos::InstanceState state = aos::InstanceStateEnum::eActive, const aos::Error& error = aos::ErrorEnum::eNone) @@ -131,217 +144,84 @@ class DatabaseTest : public Test { * Tests - imagemanager::StorageItf **********************************************************************************************************************/ -TEST_F(DatabaseTest, AddUpdateItem) -{ - ASSERT_TRUE(mDB.Init(mWorkingDir.string(), mMigrationConfig).IsNone()); - - auto item1v1 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest1", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item1v2 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "2.0.0", "sha256:digest2", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item2v1 = CreateUpdateItemData("item2", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest3", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - - // Add item1 v1 - - auto err = mDB.AddUpdateItem(item1v1); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Try to add same item again - - err = mDB.AddUpdateItem(item1v1); - ASSERT_FALSE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Add item1 v2 - - err = mDB.AddUpdateItem(item1v2); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Add item2 v1 - - err = mDB.AddUpdateItem(item2v1); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Get item1 - - auto itemData = std::make_unique>(); - - err = mDB.GetUpdateItem("item1", *itemData); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - ASSERT_EQ(itemData->Size(), 2); - EXPECT_EQ((*itemData)[0], item1v1); - EXPECT_EQ((*itemData)[1], item1v2); - - // Get item2 - - itemData->Clear(); - - err = mDB.GetUpdateItem("item2", *itemData); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - ASSERT_EQ(itemData->Size(), 1); - EXPECT_EQ((*itemData)[0], item2v1); -} - -TEST_F(DatabaseTest, UpdateUpdateItem) +TEST_F(DatabaseTest, DeployableItems) { ASSERT_TRUE(mDB.Init(mWorkingDir.string(), mMigrationConfig).IsNone()); - auto item1 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest1", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item2 = CreateUpdateItemData("item2", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest3", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - - // Add item1 - - auto err = mDB.AddUpdateItem(item1); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Add item2 - - err = mDB.AddUpdateItem(item2); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - item1.mState = aos::ItemStateEnum::eRemoved; - item2.mState = aos::ItemStateEnum::eRemoved; + const auto item1 = CreateDeployableItem("item1", "1.0.0"); + const auto item2 = CreateDeployableItem("item2", "1.0.0"); - // Update item1 - - err = mDB.UpdateUpdateItem(item1); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Update item2 - - err = mDB.UpdateUpdateItem(item2); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - // Get item1 - - auto itemData = std::make_unique>(); - - err = mDB.GetUpdateItem("item1", *itemData); + auto err = mDB.AddDeployableItem(item1); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - ASSERT_EQ(itemData->Size(), 1); - EXPECT_EQ((*itemData)[0], item1); - - // Get item2 - - itemData->Clear(); - - err = mDB.GetUpdateItem("item2", *itemData); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - ASSERT_EQ(itemData->Size(), 1); - EXPECT_EQ((*itemData)[0], item2); -} - -TEST_F(DatabaseTest, RemoveUpdateItem) -{ - ASSERT_TRUE(mDB.Init(mWorkingDir.string(), mMigrationConfig).IsNone()); - - auto item1v1 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest1", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item1v2 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "2.0.0", "sha256:digest2", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item2v1 = CreateUpdateItemData("item2", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest3", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - - // Add item 1 v1 - - auto err = mDB.AddUpdateItem(item1v1); + err = mDB.AddDeployableItem(item2); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - // Add item 1 v2 - - err = mDB.AddUpdateItem(item1v2); + err = mDB.AddItemBlob(item1.mItemID, item1.mVersion, CreateItemBlob("sha256:manifest", false, "")); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - // Add item 2 v1 + auto items = std::make_unique>(); - err = mDB.AddUpdateItem(item2v1); + err = mDB.GetAllDeployableItems(*items); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - // Remove item1 v1 with wrong version - - err = mDB.RemoveUpdateItem(item1v1.mID, "3.0.0"); - ASSERT_TRUE(err.Is(aos::ErrorEnum::eNotFound)) << aos::tests::utils::ErrorToStr(err); - - // Remove item1 v1 - - err = mDB.RemoveUpdateItem(item1v1.mID, item1v1.mVersion); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); + ASSERT_EQ(items->Size(), 2); + EXPECT_EQ((*items)[0], item1); + EXPECT_EQ((*items)[1], item2); - // Remove item2 v1 + auto [used, usedErr] = mDB.IsBlobUsed("sha256:manifest"); + ASSERT_TRUE(usedErr.IsNone()) << aos::tests::utils::ErrorToStr(usedErr); + EXPECT_TRUE(used); - err = mDB.RemoveUpdateItem(item2v1.mID, item2v1.mVersion); + err = mDB.RemoveDeployableItem(item1.mItemID, item1.mVersion); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - // Get item1 - - auto itemData = std::make_unique>(); + size_t count = 0; - err = mDB.GetUpdateItem("item1", *itemData); + Tie(count, err) = mDB.GetDeployableItemsCount(); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - ASSERT_EQ(itemData->Size(), 1); - EXPECT_EQ((*itemData)[0], item1v2); - - // Get item2 - - itemData->Clear(); - - err = mDB.GetUpdateItem("item2", *itemData); - ASSERT_TRUE(err.Is(aos::ErrorEnum::eNotFound)) << aos::tests::utils::ErrorToStr(err); - - ASSERT_EQ(itemData->Size(), 0); + EXPECT_EQ(count, 1); } -TEST_F(DatabaseTest, GetAllUpdateItems) +TEST_F(DatabaseTest, IsLayerUsed) { ASSERT_TRUE(mDB.Init(mWorkingDir.string(), mMigrationConfig).IsNone()); - auto item1v1 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest1", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item1v2 = CreateUpdateItemData("item1", aos::UpdateItemTypeEnum::eService, "2.0.0", "sha256:digest2", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); - auto item2v1 = CreateUpdateItemData("item2", aos::UpdateItemTypeEnum::eService, "1.0.0", "sha256:digest3", - aos::ItemStateEnum::eInstalled, aos::Time::Now()); + const auto item1 = CreateDeployableItem("item1", "1.0.0"); + const auto item2 = CreateDeployableItem("item2", "1.0.0"); - // Add item1 v1 + ASSERT_TRUE(mDB.AddDeployableItem(item1).IsNone()); + ASSERT_TRUE(mDB.AddDeployableItem(item2).IsNone()); - auto err = mDB.AddUpdateItem(item1v1); - ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); + // Both items reference the same layer through different blobs. + ASSERT_TRUE( + mDB.AddItemBlob(item1.mItemID, item1.mVersion, CreateItemBlob("sha256:layer1", true, "sha256:diff")).IsNone()); + ASSERT_TRUE( + mDB.AddItemBlob(item2.mItemID, item2.mVersion, CreateItemBlob("sha256:layer2", true, "sha256:diff")).IsNone()); - // Add item1 v2 + // A blob which is not a layer doesn't reference a layer even if its diff ID matches. + ASSERT_TRUE(mDB.AddItemBlob(item2.mItemID, item2.mVersion, CreateItemBlob("sha256:config", false, "sha256:other")) + .IsNone()); - err = mDB.AddUpdateItem(item1v2); + auto [used, err] = mDB.IsLayerUsed("sha256:diff"); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); + EXPECT_TRUE(used); - // Add item2 v1 - - err = mDB.AddUpdateItem(item2v1); + Tie(used, err) = mDB.IsLayerUsed("sha256:other"); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); + EXPECT_FALSE(used); - // Get all update items + ASSERT_TRUE(mDB.RemoveDeployableItem(item1.mItemID, item1.mVersion).IsNone()); - auto itemsData = std::make_unique>(); - - err = mDB.GetAllUpdateItems(*itemsData); + Tie(used, err) = mDB.IsLayerUsed("sha256:diff"); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); + EXPECT_TRUE(used); - ASSERT_EQ(itemsData->Size(), 3); - EXPECT_EQ((*itemsData)[0], item1v1); - EXPECT_EQ((*itemsData)[1], item1v2); - EXPECT_EQ((*itemsData)[2], item2v1); - - size_t count = 0; + ASSERT_TRUE(mDB.RemoveDeployableItem(item2.mItemID, item2.mVersion).IsNone()); - Tie(count, err) = mDB.GetUpdateItemsCount(); + Tie(used, err) = mDB.IsLayerUsed("sha256:diff"); ASSERT_TRUE(err.IsNone()) << aos::tests::utils::ErrorToStr(err); - - EXPECT_EQ(count, itemsData->Size()); + EXPECT_FALSE(used); } /*********************************************************************************************************************** diff --git a/src/sm/launcher/runtimes.cpp b/src/sm/launcher/runtimes.cpp index fba30a2c5..9974d8ddb 100644 --- a/src/sm/launcher/runtimes.cpp +++ b/src/sm/launcher/runtimes.cpp @@ -23,12 +23,12 @@ namespace aos::sm::launcher { **********************************************************************************************************************/ // Which parameters are used depends on which WITH_RUNTIME_* runtimes are compiled in below. -Error Runtimes::Init(const Config& config, - [[maybe_unused]] iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - [[maybe_unused]] imagemanager::ItemInfoProviderItf& itemInfoProvider, - [[maybe_unused]] networkmanager::NetworkManagerItf& networkManager, - [[maybe_unused]] iamclient::PermHandlerItf& permHandler, - [[maybe_unused]] resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, +Error Runtimes::Init(const Config& config, + [[maybe_unused]] iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, + [[maybe_unused]] common::imagemanager::ItemInfoProviderItf& itemInfoProvider, + [[maybe_unused]] networkmanager::NetworkManagerItf& networkManager, + [[maybe_unused]] iamclient::PermHandlerItf& permHandler, + [[maybe_unused]] resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, [[maybe_unused]] oci::OCISpecItf& ociSpec, [[maybe_unused]] InstanceStatusReceiverItf& statusReceiver, [[maybe_unused]] sm::utils::SystemdConnItf& systemdConn, [[maybe_unused]] launcher::InstanceIDProviderItf& instanceIDProvider, diff --git a/src/sm/launcher/runtimes.hpp b/src/sm/launcher/runtimes.hpp index 2a0a78909..1018f5043 100644 --- a/src/sm/launcher/runtimes.hpp +++ b/src/sm/launcher/runtimes.hpp @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -52,7 +52,7 @@ class Runtimes { * @return Error. */ Error Init(const Config& config, aos::iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, aos::iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& statusReceiver, utils::SystemdConnItf& systemdConn, launcher::InstanceIDProviderItf& instanceIDProvider, runtimes::StorageItf& runtimeStorage, diff --git a/src/sm/launcher/runtimes/boot/boot.cpp b/src/sm/launcher/runtimes/boot/boot.cpp index 4643dd3ee..930a12f6d 100644 --- a/src/sm/launcher/runtimes/boot/boot.cpp +++ b/src/sm/launcher/runtimes/boot/boot.cpp @@ -28,7 +28,7 @@ namespace aos::sm::launcher { **********************************************************************************************************************/ Error BootRuntime::Init(const RuntimeConfig& config, iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& statusReceiver, sm::utils::SystemdConnItf& systemdConn) { LOG_DBG() << "Init runtime" << Log::Field("type", config.mType.c_str()); diff --git a/src/sm/launcher/runtimes/boot/boot.hpp b/src/sm/launcher/runtimes/boot/boot.hpp index f364f4f09..6bea46d2c 100644 --- a/src/sm/launcher/runtimes/boot/boot.hpp +++ b/src/sm/launcher/runtimes/boot/boot.hpp @@ -12,8 +12,8 @@ #include #include +#include #include -#include #include #include @@ -49,7 +49,7 @@ class BootRuntime : public RuntimeItf { * @return Error. */ Error Init(const RuntimeConfig& config, iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& statusReceiver, sm::utils::SystemdConnItf& systemdConn); /** @@ -163,24 +163,24 @@ class BootRuntime : public RuntimeItf { std::filesystem::path GetPath(const std::string_view relativePath) const; size_t GetNextPartitionIndex(size_t currentPartition) const; - mutable std::mutex mMutex; - std::shared_ptr mPartitionManager; - std::shared_ptr mBootController; - iamclient::CurrentNodeInfoProviderItf* mCurrentNodeInfoProvider {}; - imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; - oci::OCISpecItf* mOCISpec {}; - InstanceStatusReceiverItf* mStatusReceiver {}; - RuntimeConfig mConfig; - BootConfig mBootConfig; - InstanceIdent mDefaultInstanceIdent; - utils::SystemdRebooter mSystemdRebooter; - utils::SystemdUpdateChecker mSystemdUpdateChecker; - RuntimeInfo mRuntimeInfo; - size_t mMainPartition {}; - size_t mCurrentPartition {}; - BootData mInstalled; - Optional mPending; - std::vector mPartitionDevices; + mutable std::mutex mMutex; + std::shared_ptr mPartitionManager; + std::shared_ptr mBootController; + iamclient::CurrentNodeInfoProviderItf* mCurrentNodeInfoProvider {}; + common::imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; + oci::OCISpecItf* mOCISpec {}; + InstanceStatusReceiverItf* mStatusReceiver {}; + RuntimeConfig mConfig; + BootConfig mBootConfig; + InstanceIdent mDefaultInstanceIdent; + utils::SystemdRebooter mSystemdRebooter; + utils::SystemdUpdateChecker mSystemdUpdateChecker; + RuntimeInfo mRuntimeInfo; + size_t mMainPartition {}; + size_t mCurrentPartition {}; + BootData mInstalled; + Optional mPending; + std::vector mPartitionDevices; }; } // namespace aos::sm::launcher diff --git a/src/sm/launcher/runtimes/boot/tests/boot.cpp b/src/sm/launcher/runtimes/boot/tests/boot.cpp index 0bdbdb31f..d7373c29b 100644 --- a/src/sm/launcher/runtimes/boot/tests/boot.cpp +++ b/src/sm/launcher/runtimes/boot/tests/boot.cpp @@ -12,11 +12,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include @@ -193,18 +193,18 @@ class BootRuntimeTest : public Test { .WillRepeatedly(DoAll(SetArgReferee<0>(mNodeInfo), Return(ErrorEnum::eNone))); } - PartInfo mBootAPartition; - PartInfo mBootBPartition; - NodeInfo mNodeInfo; - RuntimeConfig mConfig; - iamclient::CurrentNodeInfoProviderMock mCurrentNodeInfoProvider; - imagemanager::ItemInfoProviderMock mItemInfoProvider; - oci::OCISpecMock mOCISpec; - InstanceStatusReceiverStub mStatusReceiver; - sm::utils::SystemdConnMock mSystemdConn; - std::shared_ptr mPartitionManager {std::make_shared()}; - std::shared_ptr mMockBootController {std::make_shared()}; - TestBootRuntime mBootRuntime {mPartitionManager, mMockBootController}; + PartInfo mBootAPartition; + PartInfo mBootBPartition; + NodeInfo mNodeInfo; + RuntimeConfig mConfig; + iamclient::CurrentNodeInfoProviderMock mCurrentNodeInfoProvider; + common::imagemanager::ItemInfoProviderMock mItemInfoProvider; + oci::OCISpecMock mOCISpec; + InstanceStatusReceiverStub mStatusReceiver; + sm::utils::SystemdConnMock mSystemdConn; + std::shared_ptr mPartitionManager {std::make_shared()}; + std::shared_ptr mMockBootController {std::make_shared()}; + TestBootRuntime mBootRuntime {mPartitionManager, mMockBootController}; }; /*********************************************************************************************************************** diff --git a/src/sm/launcher/runtimes/container/container.cpp b/src/sm/launcher/runtimes/container/container.cpp index eeadd528f..67a8d8b6e 100644 --- a/src/sm/launcher/runtimes/container/container.cpp +++ b/src/sm/launcher/runtimes/container/container.cpp @@ -38,7 +38,7 @@ const char* const cDefaultHostFSBinds[] = {"bin", "sbin", "lib", "lib64", "usr"} Error ContainerRuntime::Init(const RuntimeConfig& config, iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, // cppcheck-suppress constParameterReference - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& instanceStatusReceiver, launcher::InstanceIDProviderItf& instanceIDProvider) diff --git a/src/sm/launcher/runtimes/container/container.hpp b/src/sm/launcher/runtimes/container/container.hpp index 52d71f741..25568e7ed 100644 --- a/src/sm/launcher/runtimes/container/container.hpp +++ b/src/sm/launcher/runtimes/container/container.hpp @@ -49,7 +49,7 @@ class ContainerRuntime : public RuntimeItf, public RunStatusReceiverItf, public * @return Error. */ Error Init(const RuntimeConfig& config, aos::iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, aos::iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& instanceStatusReceiver, launcher::InstanceIDProviderItf& instanceIDProvider); @@ -149,13 +149,13 @@ class ContainerRuntime : public RuntimeItf, public RunStatusReceiverItf, public std::shared_ptr mMonitoring; std::shared_ptr mContainerRunner; - imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; - networkmanager::NetworkManagerItf* mNetworkManager {}; - aos::iamclient::PermHandlerItf* mPermHandler {}; - resourcemanager::ResourceInfoProviderItf* mResourceInfoProvider {}; - oci::OCISpecItf* mOCISpec {}; - InstanceStatusReceiverItf* mInstanceStatusReceiver {}; - launcher::InstanceIDProviderItf* mInstanceIDProvider {}; + common::imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; + networkmanager::NetworkManagerItf* mNetworkManager {}; + aos::iamclient::PermHandlerItf* mPermHandler {}; + resourcemanager::ResourceInfoProviderItf* mResourceInfoProvider {}; + oci::OCISpecItf* mOCISpec {}; + InstanceStatusReceiverItf* mInstanceStatusReceiver {}; + launcher::InstanceIDProviderItf* mInstanceIDProvider {}; ContainerConfig mConfig; NodeInfo mNodeInfo; diff --git a/src/sm/launcher/runtimes/container/instance.cpp b/src/sm/launcher/runtimes/container/instance.cpp index c151dd604..7bddfcb70 100644 --- a/src/sm/launcher/runtimes/container/instance.cpp +++ b/src/sm/launcher/runtimes/container/instance.cpp @@ -35,7 +35,7 @@ static const char* const cBindEtcEntries[] = {"nsswitch.conf", "ssl"}; Instance::Instance(const InstanceInfo& instance, const ContainerConfig& config, const NodeInfo& nodeInfo, FileSystemItf& fileSystem, RunnerItf& runner, MonitoringItf& monitoring, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceIDProviderItf& instanceIDProvider) : mInstanceInfo(instance) @@ -64,7 +64,7 @@ Instance::Instance(const InstanceInfo& instance, const ContainerConfig& config, Instance::Instance(const std::string& instanceID, const ContainerConfig& config, const NodeInfo& nodeInfo, FileSystemItf& fileSystem, RunnerItf& runner, MonitoringItf& monitoring, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceIDProviderItf& instanceIDProvider) : mInstanceID(instanceID) diff --git a/src/sm/launcher/runtimes/container/instance.hpp b/src/sm/launcher/runtimes/container/instance.hpp index a0ea8736c..78b8b2524 100644 --- a/src/sm/launcher/runtimes/container/instance.hpp +++ b/src/sm/launcher/runtimes/container/instance.hpp @@ -10,9 +10,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -49,7 +49,7 @@ class Instance { */ Instance(const InstanceInfo& instance, const ContainerConfig& config, const NodeInfo& nodeInfo, FileSystemItf& fileSystem, RunnerItf& runner, MonitoringItf& monitoring, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, aos::iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceIDProviderItf& instanceIDProvider); @@ -71,7 +71,7 @@ class Instance { */ Instance(const std::string& instanceID, const ContainerConfig& config, const NodeInfo& nodeInfo, FileSystemItf& fileSystem, RunnerItf& runner, MonitoringItf& monitoring, - imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, networkmanager::NetworkManagerItf& networkManager, aos::iamclient::PermHandlerItf& permHandler, resourcemanager::ResourceInfoProviderItf& resourceInfoProvider, oci::OCISpecItf& ociSpec, InstanceIDProviderItf& instanceIDProvider); @@ -184,17 +184,17 @@ class Instance { RunStatus mRunStatus; EnvVarStatusArray mEnvVarsStatuses; - const ContainerConfig& mConfig; - const NodeInfo& mNodeInfo; - FileSystemItf& mFileSystem; - RunnerItf& mRunner; - MonitoringItf& mMonitoring; - imagemanager::ItemInfoProviderItf& mItemInfoProvider; - networkmanager::NetworkManagerItf& mNetworkManager; - aos::iamclient::PermHandlerItf& mPermHandler; - resourcemanager::ResourceInfoProviderItf& mResourceInfoProvider; - oci::OCISpecItf& mOCISpec; - InstanceIDProviderItf& mInstanceIDProvider; + const ContainerConfig& mConfig; + const NodeInfo& mNodeInfo; + FileSystemItf& mFileSystem; + RunnerItf& mRunner; + MonitoringItf& mMonitoring; + common::imagemanager::ItemInfoProviderItf& mItemInfoProvider; + networkmanager::NetworkManagerItf& mNetworkManager; + aos::iamclient::PermHandlerItf& mPermHandler; + resourcemanager::ResourceInfoProviderItf& mResourceInfoProvider; + oci::OCISpecItf& mOCISpec; + InstanceIDProviderItf& mInstanceIDProvider; mutable std::mutex mMutex; diff --git a/src/sm/launcher/runtimes/container/tests/container.cpp b/src/sm/launcher/runtimes/container/tests/container.cpp index 7414b7309..6d0ad4ced 100644 --- a/src/sm/launcher/runtimes/container/tests/container.cpp +++ b/src/sm/launcher/runtimes/container/tests/container.cpp @@ -9,13 +9,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include @@ -254,17 +254,17 @@ class ContainerRuntimeTest : public Test { ASSERT_TRUE(err.IsNone()) << "Failed to stop runtime: " << tests::utils::ErrorToStr(err); } - TestRuntime mRuntime; - NodeInfo mNodeInfo; - NiceMock mCurrentNodeInfoProviderMock; - NiceMock mItemInfoProviderMock; - NiceMock mNetworkManagerMock; - NiceMock mPermHandlerMock; - NiceMock mResourceInfoProviderMock; - NiceMock mOCISpecMock; - NiceMock mInstanceStatusReceiverMock; - RunStatusReceiverItf* mRunStatusReceiver {}; - NiceMock mInstanceIDProviderMock; + TestRuntime mRuntime; + NodeInfo mNodeInfo; + NiceMock mCurrentNodeInfoProviderMock; + NiceMock mItemInfoProviderMock; + NiceMock mNetworkManagerMock; + NiceMock mPermHandlerMock; + NiceMock mResourceInfoProviderMock; + NiceMock mOCISpecMock; + NiceMock mInstanceStatusReceiverMock; + RunStatusReceiverItf* mRunStatusReceiver {}; + NiceMock mInstanceIDProviderMock; }; /*********************************************************************************************************************** diff --git a/src/sm/launcher/runtimes/rootfs/rootfs.cpp b/src/sm/launcher/runtimes/rootfs/rootfs.cpp index 02e1c364d..43132dc16 100644 --- a/src/sm/launcher/runtimes/rootfs/rootfs.cpp +++ b/src/sm/launcher/runtimes/rootfs/rootfs.cpp @@ -295,7 +295,7 @@ RetWithError GetUpdateType(const oci::ImageManifest& manifest) **********************************************************************************************************************/ Error RootfsRuntime::Init(const RuntimeConfig& config, iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& statusReceiver, sm::utils::SystemdConnItf& systemdConn, runtimes::StorageItf& storage, fs::FileInfoProviderItf& fileInfoProvider) { diff --git a/src/sm/launcher/runtimes/rootfs/rootfs.hpp b/src/sm/launcher/runtimes/rootfs/rootfs.hpp index 9d572b712..be38eb237 100644 --- a/src/sm/launcher/runtimes/rootfs/rootfs.hpp +++ b/src/sm/launcher/runtimes/rootfs/rootfs.hpp @@ -15,9 +15,9 @@ #include #include +#include #include #include -#include #include #include @@ -61,7 +61,7 @@ class RootfsRuntime : public RuntimeItf { * @return Error. */ Error Init(const RuntimeConfig& config, iamclient::CurrentNodeInfoProviderItf& currentNodeInfoProvider, - imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, + common::imagemanager::ItemInfoProviderItf& itemInfoProvider, oci::OCISpecItf& ociSpec, InstanceStatusReceiverItf& statusReceiver, sm::utils::SystemdConnItf& systemdConn, runtimes::StorageItf& storage, fs::FileInfoProviderItf& fileInfoProvider); @@ -226,18 +226,18 @@ class RootfsRuntime : public RuntimeItf { Error PrepareUpdate(const InstanceInfo& instance); std::filesystem::path GetPath(const std::string& fileName) const; - RuntimeConfig mRuntimeConfig; - RootfsConfig mRootfsConfig; - iamclient::CurrentNodeInfoProviderItf* mCurrentNodeInfoProvider {}; - imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; - oci::OCISpecItf* mOCISpec {}; - InstanceStatusReceiverItf* mStatusReceiver {}; - runtimes::StorageItf* mStorage {}; - fs::FileInfoProviderItf* mFileInfoProvider {}; - common::utils::FSPlatform mFSPlatform; - utils::SystemdUpdateChecker mUpdateChecker; - utils::SystemdRebooter mRebooter; - InstanceIdent mDefaultInstanceIdent; + RuntimeConfig mRuntimeConfig; + RootfsConfig mRootfsConfig; + iamclient::CurrentNodeInfoProviderItf* mCurrentNodeInfoProvider {}; + common::imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; + oci::OCISpecItf* mOCISpec {}; + InstanceStatusReceiverItf* mStatusReceiver {}; + runtimes::StorageItf* mStorage {}; + fs::FileInfoProviderItf* mFileInfoProvider {}; + common::utils::FSPlatform mFSPlatform; + utils::SystemdUpdateChecker mUpdateChecker; + utils::SystemdRebooter mRebooter; + InstanceIdent mDefaultInstanceIdent; mutable std::mutex mMutex; std::mutex mHealthCheckMutex; diff --git a/src/sm/launcher/runtimes/rootfs/rootfs.md b/src/sm/launcher/runtimes/rootfs/rootfs.md index 802453192..e8ca67e35 100644 --- a/src/sm/launcher/runtimes/rootfs/rootfs.md +++ b/src/sm/launcher/runtimes/rootfs/rootfs.md @@ -26,7 +26,8 @@ any moment. The main rules are: [RootfsRuntime](rootfs.hpp) implements [aos::sm::launcher::RuntimeItf][runtime-itf] and uses: - [aos::sm::launcher::runtimes::StorageItf](../itf/storage.hpp) - stores the current and the pending instances; -- [aos::sm::imagemanager::ItemInfoProviderItf][item-info-provider-itf] - provides paths of the installed image blobs; +- [aos::common::imagemanager::ItemInfoProviderItf][item-info-provider-itf] - provides paths of the installed image + blobs; - [aos::oci::OCISpecItf][oci-spec-itf] - loads the image manifest; - [aos::fs::FileInfoProviderItf][file-info-provider-itf] - calculates the size and the sha256 hash of the copied image; - [aos::sm::launcher::InstanceStatusReceiverItf][status-receiver-itf] - receives instance statuses and reboot requests; @@ -37,7 +38,7 @@ any moment. The main rules are: - [SystemdRebooter](../utils/systemdrebooter.hpp) - reboots the node through systemd. [runtime-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/sm/launcher/itf/runtime.hpp -[item-info-provider-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/sm/imagemanager/itf/iteminfoprovider.hpp +[item-info-provider-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/common/imagemanager/itf/iteminfoprovider.hpp [oci-spec-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/common/ocispec/itf/ocispec.hpp [file-info-provider-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/common/tools/fs.hpp [status-receiver-itf]: https://github.com/aosedge/aos_core_lib_cpp/blob/develop/src/core/sm/launcher/itf/instancestatusreceiver.hpp @@ -60,7 +61,7 @@ classDiagram class StorageItf ["aos::sm::launcher::runtimes::StorageItf"] { <> } - class ItemInfoProviderItf ["aos::sm::imagemanager::ItemInfoProviderItf"] { + class ItemInfoProviderItf ["aos::common::imagemanager::ItemInfoProviderItf"] { <> } class OCISpecItf ["aos::oci::OCISpecItf"] { diff --git a/src/sm/launcher/runtimes/rootfs/tests/rootfs.cpp b/src/sm/launcher/runtimes/rootfs/tests/rootfs.cpp index 671db609a..35653aed1 100644 --- a/src/sm/launcher/runtimes/rootfs/tests/rootfs.cpp +++ b/src/sm/launcher/runtimes/rootfs/tests/rootfs.cpp @@ -30,10 +30,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -603,15 +603,15 @@ class RootfsRuntimeTest : public Test { ASSERT_TRUE(err.IsNone()) << tests::utils::ErrorToStr(err); } - RuntimeConfig mConfig; - iamclient::CurrentNodeInfoProviderMock mCurrentNodeInfoProvider; - imagemanager::ItemInfoProviderMock mItemInfoProvider; - oci::OCISpecMock mOCISpec; - InstanceStatusReceiverFailingStub mStatusReceiver; - sm::utils::SystemdConnMock mSystemdConn; - RuntimeStorageFake mStorage; - FileInfoProviderFake mFileInfoProvider; - RootfsRuntime mRootfsRuntime; + RuntimeConfig mConfig; + iamclient::CurrentNodeInfoProviderMock mCurrentNodeInfoProvider; + common::imagemanager::ItemInfoProviderMock mItemInfoProvider; + oci::OCISpecMock mOCISpec; + InstanceStatusReceiverFailingStub mStatusReceiver; + sm::utils::SystemdConnMock mSystemdConn; + RuntimeStorageFake mStorage; + FileInfoProviderFake mFileInfoProvider; + RootfsRuntime mRootfsRuntime; }; /*********************************************************************************************************************** diff --git a/src/sm/launcher/tests/launcher.cpp b/src/sm/launcher/tests/launcher.cpp index 68b4de24a..b015df51b 100644 --- a/src/sm/launcher/tests/launcher.cpp +++ b/src/sm/launcher/tests/launcher.cpp @@ -8,13 +8,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include @@ -66,17 +66,17 @@ class RuntimesTest : public Test { void TearDown() override { } - NiceMock mCurrentNodeInfoProviderMock; - NiceMock mItemInfoProviderMock; - NiceMock mNetworkManagerMock; - NiceMock mPermHandlerMock; - NiceMock mResourceInfoProviderMock; - NiceMock mOCISpecMock; - NiceMock mInstanceStatusReceiverMock; - NiceMock mSystemdConnMock; - NiceMock mInstanceIDProviderMock; - NiceMock mRuntimeStorageMock; - NiceMock mFileInfoProviderMock; + NiceMock mCurrentNodeInfoProviderMock; + NiceMock mItemInfoProviderMock; + NiceMock mNetworkManagerMock; + NiceMock mPermHandlerMock; + NiceMock mResourceInfoProviderMock; + NiceMock mOCISpecMock; + NiceMock mInstanceStatusReceiverMock; + NiceMock mSystemdConnMock; + NiceMock mInstanceIDProviderMock; + NiceMock mRuntimeStorageMock; + NiceMock mFileInfoProviderMock; }; /*********************************************************************************************************************** diff --git a/src/sm/smclient/smclient.cpp b/src/sm/smclient/smclient.cpp index ad735f568..7ccc22800 100644 --- a/src/sm/smclient/smclient.cpp +++ b/src/sm/smclient/smclient.cpp @@ -239,34 +239,34 @@ Error SMClient::SendUpdateInstancesStatuses(const Array& st return ErrorEnum::eNone; } -Error SMClient::GetBlobsInfo(const Array>& digests, Array>& urls) +Error SMClient::GetBlobInfo(const String& digest, BlobInfo& blobInfo) { std::lock_guard lock {mMutex}; - LOG_DBG() << "Get blobs info" << Log::Field("count", digests.Size()); + LOG_DBG() << "Get blob info" << Log::Field("digest", digest); if (!mStub) { return Error(ErrorEnum::eFailed, "stub not available"); } - smproto::BlobsInfosRequest request; + smproto::BlobsInfoRequest request; - for (const auto& digest : digests) { - request.add_digests(digest.CStr()); - } + request.set_digest(digest.CStr()); grpc::ClientContext context; - smproto::BlobsInfos response; + smproto::BlobInfo response; - auto status = mStub->GetBlobsInfos(&context, request, &response); + auto status = mStub->GetBlobsInfo(&context, request, &response); if (!status.ok()) { return AOS_ERROR_WRAP(Error(ErrorEnum::eFailed, status.error_message().c_str())); } - for (const auto& url : response.urls()) { - if (auto err = urls.PushBack(url.c_str()); !err.IsNone()) { - return AOS_ERROR_WRAP(err); - } + if (response.has_error()) { + return common::pbconvert::ConvertFromProto(response.error()); + } + + if (auto err = common::pbconvert::ConvertFromProto(response, digest, blobInfo); !err.IsNone()) { + return AOS_ERROR_WRAP(err); } return ErrorEnum::eNone; diff --git a/src/sm/smclient/smclient.hpp b/src/sm/smclient/smclient.hpp index 21b913635..e10ef45fd 100644 --- a/src/sm/smclient/smclient.hpp +++ b/src/sm/smclient/smclient.hpp @@ -146,17 +146,16 @@ class SMClient : public SMClientItf, public aos::iamclient::CertKeyListenerItf, */ Error SendUpdateInstancesStatuses(const Array& statuses) override; - // aos::sm::imagemanager::BlobInfoProviderItf interface + // aos::common::imagemanager::BlobInfoProviderItf interface /** - * Gets blobs info. + * Gets blob info. * - * @param digests list of blob digests. - * @param[out] urls blobs URLs. + * @param digest blob digest. + * @param[out] blobInfo blob info. * @return Error. */ - Error GetBlobsInfo( - const Array>& digests, Array>& urls) override; + Error GetBlobInfo(const String& digest, BlobInfo& blobInfo) override; // aos::cloudconnection::CloudConnectionItf interface diff --git a/src/sm/smclient/tests/smclient.cpp b/src/sm/smclient/tests/smclient.cpp index f32476b1b..c50314477 100644 --- a/src/sm/smclient/tests/smclient.cpp +++ b/src/sm/smclient/tests/smclient.cpp @@ -780,7 +780,7 @@ TEST_F(SMClientTest, SendAlert) ASSERT_TRUE(err.IsNone()) << "Stop failed"; } -TEST_F(SMClientTest, GetBlobsInfo) +TEST_F(SMClientTest, GetBlobInfo) { auto server = std::make_unique(GetConfig().mCMServerURL); auto client = std::make_unique(); @@ -828,18 +828,22 @@ TEST_F(SMClientTest, GetBlobsInfo) server->WaitSMInfo(); server->WaitNodeInstancesStatus(); - StaticArray, 2> digests; - digests.EmplaceBack("sha256:1234567890abcdef"); - digests.EmplaceBack("sha256:fedcba0987654321"); + auto blobInfo = std::make_unique(); - StaticArray, 2> urls; + err = client->GetBlobInfo("sha256:1234567890abcdef", *blobInfo); + ASSERT_TRUE(err.IsNone()) << "GetBlobInfo failed"; - err = client->GetBlobsInfo(digests, urls); - ASSERT_TRUE(err.IsNone()) << "GetBlobsInfo failed"; + const uint8_t cSHA256[] = {1, 2, 3, 4}; - ASSERT_EQ(urls.Size(), 2); - EXPECT_EQ(urls[0], "http://example.com/blobs/sha256:1234567890abcdef"); - EXPECT_EQ(urls[1], "http://example.com/blobs/sha256:fedcba0987654321"); + EXPECT_EQ(blobInfo->mDigest, "sha256:1234567890abcdef"); + ASSERT_EQ(blobInfo->mURLs.Size(), 2); + EXPECT_EQ(blobInfo->mURLs[0], "http://example.com/blobs/sha256:1234567890abcdef"); + EXPECT_EQ(blobInfo->mURLs[1], "http://mirror.example.com/blobs/sha256:1234567890abcdef"); + EXPECT_EQ(blobInfo->mSHA256, Array(cSHA256, sizeof(cSHA256))); + EXPECT_EQ(blobInfo->mSize, 1024); + + err = client->GetBlobInfo(SMServiceStub::cMissingBlobDigest, *blobInfo); + EXPECT_TRUE(err.Is(ErrorEnum::eNotFound)) << "GetBlobInfo should fail for missing blob"; err = client->Stop(); ASSERT_TRUE(err.IsNone()) << "Stop failed"; diff --git a/src/sm/smclient/tests/stubs/smservicestub.hpp b/src/sm/smclient/tests/stubs/smservicestub.hpp index 930dfd250..2eadba111 100644 --- a/src/sm/smclient/tests/stubs/smservicestub.hpp +++ b/src/sm/smclient/tests/stubs/smservicestub.hpp @@ -110,18 +110,28 @@ class SMServiceStub final : public smproto::SMService::Service, public smproto:: return grpc::Status::OK; } - grpc::Status GetBlobsInfos( - grpc::ServerContext* context, const smproto::BlobsInfosRequest* request, smproto::BlobsInfos* response) override + grpc::Status GetBlobsInfo( + grpc::ServerContext* context, const smproto::BlobsInfoRequest* request, smproto::BlobInfo* response) override { (void)context; - for (const auto& digest : request->digests()) { - response->add_urls("http://example.com/blobs/" + digest); + if (request->digest() == cMissingBlobDigest) { + response->mutable_error()->set_aos_code(static_cast(aos::ErrorEnum::eNotFound)); + response->mutable_error()->set_message("blob not found"); + + return grpc::Status::OK; } + response->add_urls("http://example.com/blobs/" + request->digest()); + response->add_urls("http://mirror.example.com/blobs/" + request->digest()); + response->set_sha256(std::string("\x01\x02\x03\x04", 4)); + response->set_size(1024); + return grpc::Status::OK; } + static constexpr auto cMissingBlobDigest = "sha256:missing"; + grpc::Status GetNodeNetworkParams(grpc::ServerContext*, const smproto::GetNodeNetworkParamsRequest* request, smproto::GetNodeNetworkParamsResponse* response) override {