Skip to content

Commit 8db8493

Browse files
committed
sm: imagemanager: implement image handler
Implement image handler interface for SM image manger. Most parts are taken from previous image module. Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
1 parent 36079fd commit 8db8493

7 files changed

Lines changed: 472 additions & 0 deletions

File tree

src/sm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ add_subdirectory(app)
2929
add_subdirectory(config)
3030
add_subdirectory(database)
3131
add_subdirectory(iamclient)
32+
add_subdirectory(imagemanager)
3233
add_subdirectory(logprovider)
3334
add_subdirectory(monitoring)
3435
add_subdirectory(networkmanager)

src/sm/app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(LIBRARIES
2020
aos::sm::config
2121
aos::sm::database
2222
aos::sm::iamclient
23+
aos::sm::imagemanager
2324
aos::sm::monitoring
2425
aos::sm::resourcemanager
2526
aos::sm::networkmanager

src/sm/imagemanager/CMakeLists.txt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#
2+
# Copyright (C) 2024 EPAM Systems, Inc.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
set(TARGET_NAME imagemanager)
8+
9+
# ######################################################################################################################
10+
# Sources
11+
# ######################################################################################################################
12+
13+
set(SOURCES imagehandler.cpp)
14+
15+
# ######################################################################################################################
16+
# Libraries
17+
# ######################################################################################################################
18+
19+
set(LIBRARIES aos::common::utils Poco::JSON)
20+
21+
# ######################################################################################################################
22+
# Target
23+
# ######################################################################################################################
24+
25+
add_module(
26+
TARGET_NAME
27+
${TARGET_NAME}
28+
LOG_MODULE
29+
STACK_USAGE
30+
${AOS_STACK_USAGE}
31+
SOURCES
32+
${SOURCES}
33+
LIBRARIES
34+
${LIBRARIES}
35+
)
36+
37+
# ######################################################################################################################
38+
# Tests
39+
# ######################################################################################################################
40+
41+
if(WITH_TEST)
42+
add_subdirectory(tests)
43+
endif()
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright (C) 2024 EPA5 Systems, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <filesystem>
8+
#include <sys/stat.h>
9+
#include <sys/xattr.h>
10+
#include <unistd.h>
11+
12+
#include <core/common/tools/logger.hpp>
13+
14+
#include <common/utils/exception.hpp>
15+
#include <common/utils/filesystem.hpp>
16+
#include <common/utils/image.hpp>
17+
18+
#include "imagehandler.hpp"
19+
20+
namespace aos::sm::imagemanager {
21+
22+
namespace {
23+
24+
/***********************************************************************************************************************
25+
* Consts
26+
**********************************************************************************************************************/
27+
28+
constexpr auto cWhiteoutPrefix = ".wh.";
29+
constexpr auto cWhiteoutOpaqueDir = ".wh..wh..opq";
30+
31+
/***********************************************************************************************************************
32+
* Static
33+
**********************************************************************************************************************/
34+
35+
void OCIWhiteoutsToOverlay(const String& path)
36+
{
37+
LOG_DBG() << "Convert OCI whiteouts to overlayfs" << Log::Field("path", path);
38+
39+
for (const auto& entry : std::filesystem::recursive_directory_iterator(path.CStr())) {
40+
const std::string baseName = entry.path().filename().string();
41+
const std::string dirName = entry.path().parent_path().string();
42+
43+
if (entry.is_directory()) {
44+
continue;
45+
}
46+
47+
if (baseName == cWhiteoutOpaqueDir) {
48+
if (auto res = setxattr(dirName.c_str(), "trusted.overlay.opaque", "y", 1, 0); res != 0) {
49+
AOS_ERROR_THROW(errno, "can't set opaque xattr");
50+
}
51+
52+
std::filesystem::remove(entry.path());
53+
54+
continue;
55+
}
56+
57+
if (baseName.rfind(cWhiteoutPrefix, 0) == 0) {
58+
auto fullPath = std::filesystem::path(dirName) / baseName.substr(strlen(cWhiteoutPrefix));
59+
60+
if (auto res = mknod(fullPath.c_str(), S_IFCHR, 0); res != 0) {
61+
AOS_ERROR_THROW(errno, "can't create whiteout node");
62+
}
63+
64+
std::filesystem::remove(entry.path());
65+
66+
continue;
67+
}
68+
}
69+
}
70+
71+
} // namespace
72+
73+
/***********************************************************************************************************************
74+
* Public
75+
**********************************************************************************************************************/
76+
77+
Error ImageHandler::UnpackLayer(const String& src, const String& dst, const String& mediaType)
78+
{
79+
try {
80+
81+
LOG_DBG() << "Unpack layer" << Log::Field("src", src) << Log::Field("dst", dst)
82+
<< Log::Field("mediaType", mediaType);
83+
84+
if (auto err = CheckMediaType(mediaType); !err.IsNone()) {
85+
return err;
86+
}
87+
88+
std::filesystem::create_directory(dst.CStr());
89+
90+
if (auto err = common::utils::UnpackTarImage(src.CStr(), dst.CStr()); !err.IsNone()) {
91+
return AOS_ERROR_WRAP(err);
92+
}
93+
94+
OCIWhiteoutsToOverlay(dst);
95+
common::utils::ChangeOwner(dst.CStr(), mUID, mGID);
96+
} catch (const std::exception& e) {
97+
return AOS_ERROR_WRAP(common::utils::ToAosError(e));
98+
}
99+
100+
return ErrorEnum::eNone;
101+
}
102+
103+
RetWithError<size_t> ImageHandler::GetUnpackedLayerSize(const String& path, const String& mediaType) const
104+
{
105+
LOG_DBG() << "Get unpacked layer size" << Log::Field("path", path) << Log::Field("mediaType", mediaType);
106+
107+
if (auto err = CheckMediaType(mediaType); !err.IsNone()) {
108+
return {0, err};
109+
}
110+
111+
auto [size, err] = common::utils::GetUnpackedArchiveSize(path.CStr(), mediaType == oci::cOCILayerTarGZip);
112+
if (!err.IsNone()) {
113+
return {0, AOS_ERROR_WRAP(err)};
114+
}
115+
116+
return size;
117+
}
118+
119+
RetWithError<StaticString<oci::cDigestLen>> ImageHandler::GetUnpackedLayerDigest(const String& path) const
120+
{
121+
LOG_DBG() << "Get unpacked layer digest" << Log::Field("path", path);
122+
123+
auto [digest, err] = common::utils::CalculateDirDigest(path.CStr());
124+
if (!err.IsNone()) {
125+
return {StaticString<oci::cDigestLen>(""), AOS_ERROR_WRAP(err)};
126+
}
127+
128+
StaticString<oci::cDigestLen> ociDigest;
129+
130+
if (err = ociDigest.Assign(digest.c_str()); !err.IsNone()) {
131+
return {StaticString<oci::cDigestLen>(""), AOS_ERROR_WRAP(err)};
132+
}
133+
134+
return ociDigest;
135+
}
136+
137+
/***********************************************************************************************************************
138+
* Private
139+
**********************************************************************************************************************/
140+
141+
Error ImageHandler::CheckMediaType(const String& mediaType) const
142+
{
143+
if (mediaType != oci::cOCILayerTar && mediaType != oci::cOCILayerTarGZip) {
144+
return AOS_ERROR_WRAP(Error(ErrorEnum::eNotSupported, "unsupported layer media type"));
145+
}
146+
147+
return ErrorEnum::eNone;
148+
}
149+
150+
} // namespace aos::sm::imagemanager
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (C) 2025 EPAM Systems, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef AOS_SM_IMAGE_IMAGEHANDLER_HPP_
8+
#define AOS_SM_IMAGE_IMAGEHANDLER_HPP_
9+
10+
#include <core/sm/imagemanager/itf/imagehandler.hpp>
11+
12+
namespace aos::sm::imagemanager {
13+
14+
/**
15+
* Image handler interface.
16+
*/
17+
class ImageHandler : public ImageHandlerItf {
18+
public:
19+
/**
20+
* Destructor.
21+
*/
22+
~ImageHandler() = default;
23+
24+
/**
25+
* Initializes image handler.
26+
*
27+
* @param uid user ID.
28+
* @param gid group ID.
29+
* @return Error.
30+
*/
31+
Error Init(uid_t uid = 0, gid_t gid = 0)
32+
{
33+
mUID = uid;
34+
mGID = gid;
35+
36+
return ErrorEnum::eNone;
37+
}
38+
39+
/**
40+
* Unpacks layer to the destination path.
41+
*
42+
* @param src source layer path.
43+
* @param dst destination path.
44+
* @param mediaType layer media type.
45+
* @return Error.
46+
*/
47+
Error UnpackLayer(const String& src, const String& dst, const String& mediaType) override;
48+
49+
/**
50+
* Returns unpacked layer size.
51+
*
52+
* @param path packed layer path.
53+
* @param mediaType layer media type.
54+
* @return RetWithError<size_t>.
55+
*/
56+
RetWithError<size_t> GetUnpackedLayerSize(const String& path, const String& mediaType) const override;
57+
58+
/**
59+
* Returns unpacked layer digest.
60+
*
61+
* @param path unpacked layer path.
62+
* @return RetWithError<StaticString<oci::cDigestLen>>.
63+
*/
64+
RetWithError<StaticString<oci::cDigestLen>> GetUnpackedLayerDigest(const String& path) const override;
65+
66+
private:
67+
Error CheckMediaType(const String& mediaType) const;
68+
69+
uid_t mUID {};
70+
gid_t mGID {};
71+
};
72+
73+
} // namespace aos::sm::imagemanager
74+
75+
#endif
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#
2+
# Copyright (C) 2024 EPAM Systems, Inc.
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
set(TARGET_NAME imagemanager_test)
8+
9+
# ######################################################################################################################
10+
# Sources
11+
# ######################################################################################################################
12+
13+
set(SOURCES imagemanager.cpp)
14+
15+
# ######################################################################################################################
16+
# Includes
17+
# ######################################################################################################################
18+
19+
set(INCLUDES ${AOS_CORE_LIB_DIR}/tests/include ${AOS_CORE_LIB_DIR}/tests/sm)
20+
21+
# ######################################################################################################################
22+
# Libraries
23+
# ######################################################################################################################
24+
25+
set(LIBRARIES aos::core::common::tests::utils aos::sm::imagemanager GTest::gmock_main)
26+
27+
# ######################################################################################################################
28+
# Target
29+
# ######################################################################################################################
30+
31+
add_test(
32+
TARGET_NAME
33+
${TARGET_NAME}
34+
LOG_MODULE
35+
SOURCES
36+
${SOURCES}
37+
INCLUDES
38+
${INCLUDES}
39+
LIBRARIES
40+
${LIBRARIES}
41+
)

0 commit comments

Comments
 (0)