diff --git a/src/cm/app/aoscore.cpp b/src/cm/app/aoscore.cpp index 4d0b6431c..d022dfdd0 100644 --- a/src/cm/app/aoscore.cpp +++ b/src/cm/app/aoscore.cpp @@ -272,7 +272,7 @@ void AosCore::InitSMController() config.mCertStorage = mConfig.mCertStorage; config.mCMServerURL = mConfig.mCMServerURL; - auto err = mSMController.Init(config, mCommunication, mIAMClient, mCertLoader, mCryptoProvider, mCommunication, + auto err = mSMController.Init(config, mCommunication, mIAMClient, mCertLoader, mCryptoProvider, mImageManager, mAlerts, mCommunication, mCommunication, mMonitoring, mLauncher, mNodeInfoProvider); AOS_ERROR_CHECK_AND_THROW(err, "can't initialize SM controller"); } diff --git a/src/cm/smcontroller/smcontroller.cpp b/src/cm/smcontroller/smcontroller.cpp index 4ae7afb16..44dfdff76 100644 --- a/src/cm/smcontroller/smcontroller.cpp +++ b/src/cm/smcontroller/smcontroller.cpp @@ -25,7 +25,7 @@ namespace aos::cm::smcontroller { Error SMController::Init(const Config& config, cloudconnection::CloudConnectionItf& cloudConnection, iamclient::CertProviderItf& certProvider, crypto::CertLoaderItf& certLoader, - crypto::x509::ProviderItf& cryptoProvider, imagemanager::BlobInfoProviderItf& blobInfoProvider, + crypto::x509::ProviderItf& cryptoProvider, imagemanager::ItemInfoProviderItf& itemInfoProvider, alerts::ReceiverItf& alertsReceiver, SenderItf& logSender, launcher::SenderItf& envVarsStatusSender, monitoring::ReceiverItf& monitoringReceiver, launcher::InstanceStatusReceiverItf& instanceStatusReceiver, nodeinfoprovider::SMInfoReceiverItf& smInfoReceiver, bool insecureConn) @@ -37,7 +37,7 @@ Error SMController::Init(const Config& config, cloudconnection::CloudConnectionI mCertProvider = &certProvider; mCertLoader = &certLoader; mCryptoProvider = &cryptoProvider; - mBlobInfoProvider = &blobInfoProvider; + mItemInfoProvider = &itemInfoProvider; mAlertsReceiver = &alertsReceiver; mLogSender = &logSender; mEnvVarsStatusSender = &envVarsStatusSender; @@ -286,37 +286,19 @@ grpc::Status SMController::RegisterSM(grpc::ServerContext* return grpc::Status::OK; } -grpc::Status SMController::GetBlobsInfos(grpc::ServerContext* /*context*/, - const servicemanager::v5::BlobsInfosRequest* request, servicemanager::v5::BlobsInfos* response) +grpc::Status SMController::GetBlobsInfos(grpc::ServerContext*, const servicemanager::v5::BlobsInfosRequest* request, + servicemanager::v5::BlobsInfos* response) { - LOG_DBG() << "Get blobs info request received: digests count=" << request->digests_size(); - - std::vector> digests; - digests.reserve(request->digests_size()); + LOG_DBG() << "Get blobs info request received" << Log::Field("digestsCount", request->digests_size()); for (int i = 0; i < request->digests_size(); ++i) { - digests.push_back(request->digests(i).c_str()); - } - - auto digestsArray = Array>(digests.data(), digests.size()); - - std::vector blobsInfo(request->digests_size()); - auto blobsInfoArray = Array(blobsInfo.data(), blobsInfo.size()); - - if (auto err = mBlobInfoProvider->GetBlobsInfos(digestsArray, blobsInfoArray); !err.IsNone()) { - return grpc::Status(grpc::StatusCode::INTERNAL, err.Message()); - } - - if (blobsInfoArray.Size() != digestsArray.Size()) { - return grpc::Status(grpc::StatusCode::NOT_FOUND, "some blobs info not found"); - } + StaticString digestURL; - for (const auto& blobInfo : blobsInfo) { - if (blobInfo.mURLs.Size() != 1) { - return grpc::Status(grpc::StatusCode::NOT_FOUND, "blob URL not found"); + if (auto err = mItemInfoProvider->GetBlobURL(request->digests(i).c_str(), digestURL); !err.IsNone()) { + return grpc::Status(grpc::StatusCode::INTERNAL, err.Message()); } - response->add_urls(blobInfo.mURLs[0].CStr()); + response->add_urls(digestURL.CStr()); } return grpc::Status::OK; diff --git a/src/cm/smcontroller/smcontroller.hpp b/src/cm/smcontroller/smcontroller.hpp index 4fdea4c2f..1fb77df76 100644 --- a/src/cm/smcontroller/smcontroller.hpp +++ b/src/cm/smcontroller/smcontroller.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -49,7 +49,7 @@ class SMController : public SMControllerItf, * @param certProvider certificate provider. * @param certLoader certificate loader. * @param cryptoProvider crypto provider. - * @param blobInfoProvider blob info provider. + * @param itemInfoProvider item info provider. * @param alertsReceiver alerts receiver. * @param logSender log sender. * @param envVarsStatusSender env vars status sender. @@ -61,7 +61,7 @@ class SMController : public SMControllerItf, */ Error Init(const Config& config, cloudconnection::CloudConnectionItf& cloudConnection, aos::iamclient::CertProviderItf& certProvider, crypto::CertLoaderItf& certLoader, - crypto::x509::ProviderItf& cryptoProvider, imagemanager::BlobInfoProviderItf& blobInfoProvider, + crypto::x509::ProviderItf& cryptoProvider, imagemanager::ItemInfoProviderItf& itemInfoProvider, alerts::ReceiverItf& alertsReceiver, SenderItf& logSender, launcher::SenderItf& envVarsStatusSender, monitoring::ReceiverItf& monitoringReceiver, launcher::InstanceStatusReceiverItf& instanceStatusReceiver, nodeinfoprovider::SMInfoReceiverItf& smInfoReceiver, bool insecureConn = false); @@ -202,7 +202,7 @@ class SMController : public SMControllerItf, crypto::CertLoaderItf* mCertLoader {}; crypto::x509::ProviderItf* mCryptoProvider {}; aos::iamclient::CertProviderItf* mCertProvider {}; - imagemanager::BlobInfoProviderItf* mBlobInfoProvider {}; + imagemanager::ItemInfoProviderItf* mItemInfoProvider {}; alerts::ReceiverItf* mAlertsReceiver {}; SenderItf* mLogSender {}; launcher::SenderItf* mEnvVarsStatusSender {}; diff --git a/src/cm/smcontroller/tests/smcontroller.cpp b/src/cm/smcontroller/tests/smcontroller.cpp index 498043086..19586d98a 100644 --- a/src/cm/smcontroller/tests/smcontroller.cpp +++ b/src/cm/smcontroller/tests/smcontroller.cpp @@ -11,11 +11,11 @@ #include #include "stubs/alertsreceiverstub.hpp" -#include "stubs/blobinfoproviderstub.hpp" #include "stubs/certloaderstub.hpp" #include "stubs/certproviderstub.hpp" #include "stubs/cloudconnectionstub.hpp" #include "stubs/instancestatusreceiverstub.hpp" +#include "stubs/iteminfoproviderstub.hpp" #include "stubs/launchersenderstub.hpp" #include "stubs/monitoringreceiverstub.hpp" #include "stubs/smclientstub.hpp" @@ -43,7 +43,7 @@ class SMControllerTest : public Test { mConfig.mCMServerURL = "localhost:8094"; auto err = mSMController.Init(mConfig, mCloudConnection, mCertProvider, mCertLoader, mX509Provider, - mBlobInfoProvider, mAlertsReceiver, mSMControllerSender, mLauncherSender, mMonitoringReceiver, + mItemInfoProvider, mAlertsReceiver, mSMControllerSender, mLauncherSender, mMonitoringReceiver, mInstanceStatusReceiver, mSMInfoReceiver, true); ASSERT_TRUE(err.IsNone()) << err.Message(); @@ -94,7 +94,7 @@ class SMControllerTest : public Test { iamclient::CertProviderStub mCertProvider; crypto::CertLoaderStub mCertLoader; crypto::x509::ProviderStub mX509Provider; - BlobInfoProviderStub mBlobInfoProvider; + ItemInfoProviderStub mItemInfoProvider; alerts::ReceiverStub mAlertsReceiver; SenderStub mSMControllerSender; launcher::SenderStub mLauncherSender; @@ -727,14 +727,8 @@ TEST_F(SMControllerTest, GetBlobsInfos) const std::string digest = "sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; const std::string url = "https://example.com/blob.tar"; - // 1) Setup blob info in stub - BlobInfo blobInfo; - blobInfo.mDigest.Assign(digest.c_str()); - blobInfo.mSize = 1024; - if (auto err = blobInfo.mURLs.EmplaceBack(url.c_str()); !err.IsNone()) { - FAIL() << "Failed to set blob URL: " << err.Message(); - } - mBlobInfoProvider.SetBlobInfo(String(digest.c_str()), blobInfo); + // 1) Setup blob URL in stub + mItemInfoProvider.SetBlobURL(digest, url); // 2) Start client SMClientStub client; diff --git a/src/cm/smcontroller/tests/stubs/blobinfoproviderstub.hpp b/src/cm/smcontroller/tests/stubs/blobinfoproviderstub.hpp deleted file mode 100644 index 47318bf71..000000000 --- a/src/cm/smcontroller/tests/stubs/blobinfoproviderstub.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2025 EPAM Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef AOS_CM_SMCONTROLLER_TESTS_STUBS_BLOBINFOPROVIDERSTUB_HPP_ -#define AOS_CM_SMCONTROLLER_TESTS_STUBS_BLOBINFOPROVIDERSTUB_HPP_ - -#include -#include - -#include - -namespace aos::cm::smcontroller { - -/** - * Blob info provider stub. - */ -class BlobInfoProviderStub : public imagemanager::BlobInfoProviderItf { -public: - /** - * Sets blob info for a digest. - * - * @param digest blob digest. - * @param blobInfo blob info. - */ - void SetBlobInfo(const String& digest, const BlobInfo& blobInfo) { mBlobInfoMap[digest.CStr()] = blobInfo; } - - /** - * Returns blobs info. - * - * @param digests list of blob digests. - * @param[out] blobsInfo blobs info. - * @return Error. - */ - Error GetBlobsInfos(const Array>& digests, Array& blobsInfo) override - { - blobsInfo.Clear(); - - for (const auto& digest : digests) { - auto it = mBlobInfoMap.find(digest.CStr()); - if (it == mBlobInfoMap.end()) { - return Error(ErrorEnum::eNotFound, "Blob info not found"); - } - - if (auto err = blobsInfo.EmplaceBack(it->second); !err.IsNone()) { - return err; - } - } - - return ErrorEnum::eNone; - } - -private: - std::map mBlobInfoMap; -}; - -} // namespace aos::cm::smcontroller - -#endif diff --git a/src/cm/smcontroller/tests/stubs/iteminfoproviderstub.hpp b/src/cm/smcontroller/tests/stubs/iteminfoproviderstub.hpp new file mode 100644 index 000000000..dc9b8119f --- /dev/null +++ b/src/cm/smcontroller/tests/stubs/iteminfoproviderstub.hpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2025 EPAM Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef AOS_CM_SMCONTROLLER_TESTS_STUBS_ITEMINFOPROVIDERSTUB_HPP_ +#define AOS_CM_SMCONTROLLER_TESTS_STUBS_ITEMINFOPROVIDERSTUB_HPP_ + +#include +#include + +#include + +namespace aos::cm::smcontroller { + +/** + * Item info provider stub. + */ +class ItemInfoProviderStub : public imagemanager::ItemInfoProviderItf { +public: + /** + * Sets blob URL by its digest. + * + * @param digest blob digest. + * @param url blob URL. + */ + void SetBlobURL(const std::string& digest, const std::string& url) { mBlobURLMap[digest] = url; } + + /** + * Returns update item index digest. + * + * @param itemID update item ID. + * @param version update item version. + * @param[out] digest result item digest. + * @return Error. + */ + Error GetIndexDigest(const String& itemID, const String& version, String& digest) const override + { + (void)itemID; + (void)version; + (void)digest; + + return ErrorEnum::eNone; + } + + /** + * Returns blob path by its digest. + * + * @param digest blob digest. + * @param[out] path result blob path. + * @return Error. + */ + Error GetBlobPath(const String& digest, String& path) const override + { + (void)digest; + (void)path; + + return ErrorEnum::eNone; + } + + /** + * Returns blob URL by its digest. + * + * @param digest blob digest. + * @param[out] url result blob URL. + * @return Error. + */ + Error GetBlobURL(const String& digest, String& url) const override + { + auto it = mBlobURLMap.find(digest.CStr()); + if (it == mBlobURLMap.end()) { + return Error(ErrorEnum::eNotFound, "blob URL not found"); + } + + url = it->second.c_str(); + + return ErrorEnum::eNone; + } + + /** + * Returns item current version. + * + * @param itemID update item ID. + * @param[out] version result item version. + * @return Error. + */ + Error GetItemCurrentVersion(const String& itemID, String& version) const override + { + (void)itemID; + (void)version; + + return ErrorEnum::eNone; + } + +private: + std::unordered_map mBlobURLMap; +}; + +} // namespace aos::cm::smcontroller + +#endif diff --git a/src/common/fileserver/fileserver.cpp b/src/common/fileserver/fileserver.cpp index 2c6b85fc3..532963de0 100644 --- a/src/common/fileserver/fileserver.cpp +++ b/src/common/fileserver/fileserver.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include @@ -22,6 +21,8 @@ #include "fileserver.hpp" +namespace fs = std::filesystem; + namespace aos::common::fileserver { namespace { @@ -59,18 +60,22 @@ std::string GetMimeType(const std::string& ext) Error Fileserver::Init(const std::string& serverURL, const std::string& rootDir) { try { + LOG_DBG() << "Init fileserver" << Log::Field("serverURL", serverURL.c_str()) + << Log::Field("rootDir", rootDir.c_str()); + mRootDir = rootDir; - Poco::URI uri(serverURL); + mURI = serverURL.c_str(); - mHost = uri.getHost(); - mPort = uri.getPort(); + if (mURI.getScheme().empty()) { + mURI.setScheme("http"); + } - if (mHost.empty()) { - mHost = "localhost"; + if (mURI.getHost().empty()) { + mURI.setHost("localhost"); } - if (mPort == 0) { - mPort = cDefaultPort; + if (mURI.getPort() == 0) { + mURI.setPort(cDefaultPort); } } catch (const std::exception& e) { return common::utils::ToAosError(e); @@ -81,20 +86,14 @@ Error Fileserver::Init(const std::string& serverURL, const std::string& rootDir) Error Fileserver::TranslateFilePathURL(const String& filePath, String& outURL) { - if (mHost.empty() || mPort == 0) { + if (mURI.getScheme().empty() || mURI.getHost().empty() || mURI.getPort() == 0) { return Error(ErrorEnum::eWrongState, "server is not started"); } try { - Poco::URI uri(filePath.CStr()); - std::filesystem::path path = uri.getPath(); - - auto filename = path.filename(); + auto uri = mURI; - uri.setScheme("http"); - uri.setHost(mHost); - uri.setPort(mPort); - uri.setPath(filename.string()); + uri.setPath(fs::relative(fs::path(filePath.CStr()), mRootDir).string()); outURL = uri.toString().c_str(); @@ -179,7 +178,7 @@ Error Fileserver::Start() mThread = std::thread([this]() { try { mServer = std::make_unique(new FileRequestHandlerFactory(mRootDir), - Poco::Net::ServerSocket(mPort), new Poco::Net::HTTPServerParams); + Poco::Net::ServerSocket(mURI.getPort()), new Poco::Net::HTTPServerParams); mServer->start(); } catch (const std::exception& e) { diff --git a/src/common/fileserver/fileserver.hpp b/src/common/fileserver/fileserver.hpp index fc3d8d311..2d810f96a 100644 --- a/src/common/fileserver/fileserver.hpp +++ b/src/common/fileserver/fileserver.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -117,8 +118,7 @@ class Fileserver : public cm::fileserver::FileServerItf { std::string mRootDir; std::unique_ptr mServer; - std::string mHost; - uint16_t mPort {}; + Poco::URI mURI; std::thread mThread; }; diff --git a/src/common/fileserver/tests/fileserver.cpp b/src/common/fileserver/tests/fileserver.cpp index 3f1cbdb3a..e255da0a5 100644 --- a/src/common/fileserver/tests/fileserver.cpp +++ b/src/common/fileserver/tests/fileserver.cpp @@ -58,7 +58,7 @@ class CommonFileserverTest : public ::testing::Test { TEST_F(CommonFileserverTest, TranslateFilePathURL) { StaticString<256> url; - auto err = mFileserver.TranslateFilePathURL("file://download/test_file.dat", url); + auto err = mFileserver.TranslateFilePathURL("download/test_file.dat", url); EXPECT_EQ(err, ErrorEnum::eNone); EXPECT_EQ(url, "http://localhost:8000/test_file.dat"); diff --git a/src/sm/launcher/runtimes/container/container.cpp b/src/sm/launcher/runtimes/container/container.cpp index 5d2c2e665..9e0b07407 100644 --- a/src/sm/launcher/runtimes/container/container.cpp +++ b/src/sm/launcher/runtimes/container/container.cpp @@ -152,9 +152,30 @@ Error ContainerRuntime::StartInstance(const InstanceInfo& instanceInfo, Instance if (auto it = mCurrentInstances.find(static_cast(instanceInfo)); it != mCurrentInstances.end()) { - return AOS_ERROR_WRAP(Error(ErrorEnum::eAlreadyExist, "instance already running")); + + instance = it->second; + instance->GetStatus(status); + + if (status.mState == InstanceStateEnum::eActive) { + LOG_DBG() << "Instance is already running" + << Log::Field("instance", static_cast(instanceInfo)); + + return ErrorEnum::eNone; + } + } + } + + if (instance) { + if (auto err = instance->Stop(); !err.IsNone()) { + LOG_ERR() << "Failed to stop instance" + << Log::Field("instance", static_cast(instanceInfo)) << Log::Field(err); } + instance->GetStatus(status); + SendInstanceStatus(status); + } else { + std::lock_guard lock {mMutex}; + instance = std::make_shared(instanceInfo, mConfig, mNodeInfo, *mFileSystem, *mRunner, *mMonitoring, *mItemInfoProvider, *mNetworkManager, *mPermHandler, *mResourceInfoProvider, *mOCISpec); @@ -192,7 +213,9 @@ Error ContainerRuntime::StopInstance(const InstanceIdent& instanceIdent, Instanc auto it = mCurrentInstances.find(static_cast(instanceIdent)); if (it == mCurrentInstances.end()) { - return AOS_ERROR_WRAP(Error(ErrorEnum::eNotFound, "instance not running")); + LOG_DBG() << "Instance is not running" << Log::Field("instance", instanceIdent); + + return ErrorEnum::eNone; } instance = it->second; diff --git a/src/sm/launcher/runtimes/container/tests/container.cpp b/src/sm/launcher/runtimes/container/tests/container.cpp index dc5761847..7f4855b55 100644 --- a/src/sm/launcher/runtimes/container/tests/container.cpp +++ b/src/sm/launcher/runtimes/container/tests/container.cpp @@ -300,7 +300,7 @@ TEST_F(ContainerRuntimeTest, StartInstance) // Start the same instance again err = mRuntime.StartInstance(instance, *status); - EXPECT_TRUE(err.Is(ErrorEnum::eAlreadyExist)) << "Wrong error: " << tests::utils::ErrorToStr(err); + EXPECT_TRUE(err.IsNone()) << "Failed to start instance: " << tests::utils::ErrorToStr(err); } TEST_F(ContainerRuntimeTest, StopInstance) @@ -355,7 +355,7 @@ TEST_F(ContainerRuntimeTest, StopInstance) // Stop the same instance again err = mRuntime.StopInstance(static_cast(instance), *status); - EXPECT_TRUE(err.Is(ErrorEnum::eNotFound)) << "Wrong error: " << tests::utils::ErrorToStr(err); + EXPECT_TRUE(err.IsNone()) << "Failed to stop instance: " << tests::utils::ErrorToStr(err); } TEST_F(ContainerRuntimeTest, UpdateInstanceStatus)