Skip to content

Commit e641aa7

Browse files
author
voidzeronull0
committed
Add initial TImageManager
1 parent f83ca2b commit e641aa7

5 files changed

Lines changed: 214 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ FetchContent_Declare(
4747
GIT_TAG v2.5.0
4848
)
4949

50-
FetchContent_MakeAvailable(cli11)
50+
#FetchContent_MakeAvailable(cli11)
5151

5252
include_directories(${cli11_SOURCE_DIR}/include)
5353
# </Cli11>
@@ -69,14 +69,14 @@ include(GoogleTest)
6969
set(protobuf_BUILD_TESTS OFF CACHE BOOL "" FORCE)
7070
set(protobuf_INSTALL OFF CACHE BOOL "" FORCE)
7171

72-
FetchContent_Declare(
72+
#FetchContent_Declare(
7373
protobuf
7474
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
7575
GIT_TAG v21.4
7676
SOURCE_SUBDIR cmake
7777
)
7878

79-
FetchContent_MakeAvailable(protobuf)
79+
#FetchContent_MakeAvailable(protobuf)
8080

8181
include_directories(${protobuf_INCLUDE_DIR})
8282
include_directories(${protobuf_SOURCE_DIR}/src)
@@ -97,6 +97,38 @@ FetchContent_MakeAvailable(json)
9797
include_directories(${json_SOURCE_DIR}/include)
9898
# </nlohmann_json>
9999

100+
# <libcurl>
101+
set(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
102+
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
103+
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
104+
105+
FetchContent_Declare(
106+
curl
107+
GIT_REPOSITORY https://github.com/curl/curl.git
108+
GIT_TAG curl-8_7_1
109+
)
110+
111+
FetchContent_MakeAvailable(curl)
112+
113+
include_directories(${curl_SOURCE_DIR}/include)
114+
# <libcurl>
115+
116+
# <libarchive>
117+
set(ENABLE_TEST OFF CACHE BOOL "" FORCE)
118+
set(ENABLE_CPIO OFF CACHE BOOL "" FORCE)
119+
set(ENABLE_CAT OFF CACHE BOOL "" FORCE)
120+
121+
FetchContent_Declare(
122+
libarchive
123+
GIT_REPOSITORY https://github.com/libarchive/libarchive.git
124+
GIT_TAG v3.7.2
125+
)
126+
127+
FetchContent_MakeAvailable(libarchive)
128+
129+
include_directories(${libarchive_SOURCE_DIR}/libarchive)
130+
# </libarchive>
131+
100132
# ========================================== End install dependencies ==========================================
101133

102134
# Start flags
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1+
# source:
12

3+
set(SOURCES imagemanager.cpp)
4+
set(HEADERS imagemanager.hpp)
5+
add_library(imagemanager ${SOURCES} ${HEADERS})
6+
apply_compile_flags(imagemanager)
7+
target_link_libraries(imagemanager PUBLIC curl archive)
8+
9+
# tests:
10+
11+
add_executable(imagemanager_ut imagemanager_ut.cpp)
12+
apply_compile_flags(imagemanager_ut)
13+
14+
target_link_libraries(
15+
imagemanager_ut
16+
PRIVATE
17+
GTest::gtest
18+
imagemanager
19+
archive
20+
curl
21+
)
22+
23+
gtest_discover_tests(imagemanager_ut)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#include "imagemanager.hpp"
2+
3+
namespace NImageManager {
4+
5+
TStatus TImageManager::Install(Images image) {
6+
TStatus status;
7+
8+
status = DownloadImage(image);
9+
if (status.Code == TStatus::Failed) {
10+
status.Error = "TImageManager::Install: " + status.Error;
11+
return status;
12+
}
13+
14+
status = DearchiveImage();
15+
return { TStatus::Success };
16+
}
17+
18+
// GOD FORBID US - curl requires C-styled function with this signature
19+
// TBD - move it to os.hpp - VoidZeroNull0
20+
size_t WriteArchive(void* ptr, size_t size, size_t nmemb, FILE* stream) {
21+
return fwrite(ptr, size, nmemb, stream);
22+
}
23+
24+
TStatus TImageManager::DownloadImage(Images image) {
25+
TStatus status;
26+
27+
CURL* curl = curl_easy_init();
28+
if (!curl) {
29+
status.Code = TStatus::Failed;
30+
status.Error = "TImageManager::DownloadImage:Could not init curl";
31+
return status;
32+
}
33+
34+
std::string url;
35+
CurrentImageName = "";
36+
if (image == Images::Alpine) {
37+
url = "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-minirootfs-3.21.3-x86_64.tar.gz";
38+
CurrentImageName = "alpine";
39+
}
40+
else {
41+
status.Code = TStatus::Failed;
42+
status.Error = "TImageManager::DownloadImage: Non-implemented image";
43+
return status;
44+
}
45+
46+
std::string path = MakeString() << ImagesLocation << CurrentImageName << ".tar.gz";
47+
48+
FILE* file = fopen(path.c_str(), "wb");
49+
if (!file) {
50+
status.Code = TStatus::Failed;
51+
status.Error = "TImageManager::DownloadImage: Could not create file";
52+
return status;
53+
}
54+
55+
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
56+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteArchive);
57+
curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
58+
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
59+
60+
CURLcode result = curl_easy_perform(curl);
61+
if (result != CURLE_OK) {
62+
status.Code = TStatus::Failed;
63+
status.Error = MakeString() << "TImageManager::DownloadImage: Curl result error" << result;
64+
fclose(file);
65+
curl_easy_cleanup(curl);
66+
return status;
67+
}
68+
69+
fclose(file);
70+
curl_easy_cleanup(curl);
71+
72+
return { TStatus::Success };
73+
}
74+
75+
TStatus TImageManager::DearchiveImage() {
76+
TStatus status;
77+
78+
struct archive* a = archive_read_new();
79+
struct archive* ext = archive_write_disk_new();
80+
struct archive_entry* entry;
81+
82+
archive_read_support_format_tar(a);
83+
archive_read_support_filter_gzip(a); // для .gz
84+
85+
std::string path = MakeString() << ImagesLocation << CurrentImageName << ".tar.gz";
86+
if (archive_read_open_filename(a, path.c_str(), 10240)) {
87+
status.Code = TStatus::Failed;
88+
status.Error = "TImageManager::DownloadImage: Could not open archive";
89+
return status;
90+
}
91+
92+
path = MakeString() << ImagesLocation << "/" << CurrentImageName;
93+
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
94+
const char* currentFile = archive_entry_pathname(entry);
95+
std::string fullOutputPath = path + "/" + currentFile;
96+
archive_entry_set_pathname(entry, fullOutputPath.c_str());
97+
98+
archive_write_header(ext, entry);
99+
const void* buff;
100+
size_t size;
101+
la_int64_t offset;
102+
103+
while (archive_read_data_block(a, &buff, &size, &offset) == ARCHIVE_OK) {
104+
archive_write_data_block(ext, buff, size, offset);
105+
}
106+
}
107+
108+
archive_read_close(a);
109+
archive_read_free(a);
110+
archive_write_close(ext);
111+
archive_write_free(ext);
112+
113+
return { TStatus::Success };
114+
}
115+
} // namespace NImageManager
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <dasboot/cru/common.hpp>
2+
#include <dasboot/cru/os.hpp>
3+
4+
#include <curl/curl.h>
5+
#include <archive.h>
6+
#include <archive_entry.h>
7+
8+
namespace NImageManager {
9+
using TStatus = NCommon::TStatus;
10+
11+
enum Images {
12+
Alpine
13+
};
14+
15+
class TImageManager {
16+
std::string ImagesLocation = "/var/lib/dasboot/images/";
17+
std::string CurrentImageName;
18+
19+
public:
20+
TStatus Install(Images image);
21+
22+
private:
23+
TStatus DownloadImage(Images image);
24+
TStatus DearchiveImage();
25+
};
26+
} // namespace NImageManager
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <gtest/gtest.h>
2+
3+
#include <dasboot/core/coordinator/imagemanager.hpp>
4+
5+
TEST(ImageCoordinator, TestInstall) {
6+
NImageManager::TImageManager imageManager;
7+
imageManager.Install(NImageManager::Images::Alpine);
8+
EXPECT_EQ(true, true);
9+
}
10+
11+
int main(int argc, char** argv) {
12+
::testing::InitGoogleTest(&argc, argv);
13+
auto result = RUN_ALL_TESTS();
14+
15+
return result;
16+
}

0 commit comments

Comments
 (0)