1 Star 0 Fork 44

严莹/iSulad

forked from src-openEuler/iSulad 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0040-add-support-for-GetContainerEvents.patch 96.09 KB
一键复制 编辑 原始数据 按行查看 历史
liuxu 提交于 2024-04-20 10:00 . upgrade from upstream
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601
From 745497bdc5c5192709ecc7b3edc91a5170f5b30e Mon Sep 17 00:00:00 2001
From: jikai <jikai11@huawei.com>
Date: Fri, 29 Mar 2024 09:33:38 +0000
Subject: [PATCH 40/69] add support for GetContainerEvents
Signed-off-by: jikai <jikai11@huawei.com>
---
src/daemon/CMakeLists.txt | 3 +
src/daemon/common/cri/v1/v1_cri_helpers.cc | 205 +++++++++++++++
src/daemon/common/cri/v1/v1_cri_helpers.h | 5 +
.../{entry => common}/cri/v1/v1_naming.cc | 0
.../{entry => common}/cri/v1/v1_naming.h | 0
src/daemon/config/isulad_config.c | 1 +
.../entry/connect/grpc/cri/cri_service.cc | 3 +-
.../entry/connect/grpc/cri/cri_service.h | 1 +
.../cri/v1/cri_v1_runtime_runtime_service.cc | 147 ++++++++++-
.../cri/v1/cri_v1_runtime_runtime_service.h | 11 +-
src/daemon/entry/connect/grpc/grpc_service.cc | 6 +-
.../v1/v1_cri_container_manager_service.cc | 203 +--------------
.../cri/v1/v1_cri_container_manager_service.h | 13 -
.../v1/v1_cri_pod_sandbox_manager_service.cc | 92 ++++++-
.../v1/v1_cri_pod_sandbox_manager_service.h | 10 +-
.../entry/cri/v1/v1_cri_runtime_service.h | 4 +-
.../cri/v1/v1_cri_runtime_service_impl.cc | 10 +-
.../cri/v1/v1_cri_runtime_service_impl.h | 7 +-
src/daemon/executor/container_cb/execution.c | 25 ++
.../executor/container_cb/execution_create.c | 12 +
src/daemon/mailbox/CMakeLists.txt | 11 +
src/daemon/mailbox/mailbox.c | 167 +++++++++++++
src/daemon/mailbox/mailbox.h | 82 ++++++
src/daemon/mailbox/mailbox_message.c | 94 +++++++
src/daemon/mailbox/mailbox_message.h | 50 ++++
src/daemon/mailbox/message_queue.c | 234 ++++++++++++++++++
src/daemon/mailbox/message_queue.h | 57 +++++
src/daemon/mailbox/message_subscriber.c | 85 +++++++
src/daemon/mailbox/message_subscriber.h | 41 +++
src/daemon/modules/api/container_api.h | 5 +
.../modules/container/supervisor/supervisor.c | 18 ++
src/daemon/sandbox/sandbox.cc | 9 +
src/utils/cutils/blocking_queue.c | 185 ++++++++++++++
src/utils/cutils/blocking_queue.h | 66 +++++
test/mocks/mailbox_mock.cc | 30 +++
test/mocks/mailbox_mock.h | 30 +++
test/sandbox/controller/shim/CMakeLists.txt | 1 +
test/sandbox/sandbox/CMakeLists.txt | 2 +
38 files changed, 1681 insertions(+), 244 deletions(-)
rename src/daemon/{entry => common}/cri/v1/v1_naming.cc (100%)
rename src/daemon/{entry => common}/cri/v1/v1_naming.h (100%)
create mode 100644 src/daemon/mailbox/CMakeLists.txt
create mode 100644 src/daemon/mailbox/mailbox.c
create mode 100644 src/daemon/mailbox/mailbox.h
create mode 100644 src/daemon/mailbox/mailbox_message.c
create mode 100644 src/daemon/mailbox/mailbox_message.h
create mode 100644 src/daemon/mailbox/message_queue.c
create mode 100644 src/daemon/mailbox/message_queue.h
create mode 100644 src/daemon/mailbox/message_subscriber.c
create mode 100644 src/daemon/mailbox/message_subscriber.h
create mode 100644 src/utils/cutils/blocking_queue.c
create mode 100644 src/utils/cutils/blocking_queue.h
create mode 100644 test/mocks/mailbox_mock.cc
create mode 100644 test/mocks/mailbox_mock.h
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index d5280c88..29af3dca 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -3,6 +3,7 @@
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} daemon_top_srcs)
add_subdirectory(executor)
add_subdirectory(entry)
+add_subdirectory(mailbox)
add_subdirectory(modules)
add_subdirectory(config)
add_subdirectory(common)
@@ -11,6 +12,7 @@ set(local_daemon_srcs
${daemon_top_srcs}
${EXECUTOR_SRCS}
${ENTRY_SRCS}
+ ${MAILBOX_SRCS}
${MODULES_SRCS}
${CONFIG_SRCS}
${DAEMON_COMMON_SRCS}
@@ -20,6 +22,7 @@ set(local_daemon_incs
${CMAKE_CURRENT_SOURCE_DIR}
${EXECUTOR_INCS}
${ENTRY_INCS}
+ ${MAILBOX_INCS}
${MODULES_INCS}
${CONFIG_INCS}
${DAEMON_COMMON_INCS}
diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc
index c57301ce..a3488894 100644
--- a/src/daemon/common/cri/v1/v1_cri_helpers.cc
+++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc
@@ -32,6 +32,7 @@
#include "service_container_api.h"
#include "isulad_config.h"
#include "sha256.h"
+#include "v1_naming.h"
namespace CRIHelpersV1 {
@@ -458,4 +459,208 @@ void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecu
}
}
+void PackContainerImageToStatus(
+ container_inspect *inspect, std::unique_ptr<runtime::v1::ContainerStatus> &contStatus, Errors &error)
+{
+ if (inspect->config == nullptr) {
+ return;
+ }
+
+ if (inspect->config->image != nullptr) {
+ contStatus->mutable_image()->set_image(inspect->config->image);
+ }
+
+ contStatus->set_image_ref(CRIHelpers::ToPullableImageID(inspect->config->image, inspect->config->image_ref));
+}
+
+void UpdateBaseStatusFromInspect(
+ container_inspect *inspect, int64_t &createdAt, int64_t &startedAt, int64_t &finishedAt,
+ std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
+{
+ runtime::v1::ContainerState state { runtime::v1::CONTAINER_UNKNOWN };
+ std::string reason;
+ std::string message;
+ int32_t exitCode { 0 };
+
+ if (inspect->state == nullptr) {
+ goto pack_status;
+ }
+
+ if (inspect->state->running) {
+ // Container is running
+ state = runtime::v1::CONTAINER_RUNNING;
+ } else {
+ // Container is not running.
+ if (finishedAt != 0) { // Case 1
+ state = runtime::v1::CONTAINER_EXITED;
+ if (inspect->state->exit_code == 0) {
+ reason = "Completed";
+ } else {
+ reason = "Error";
+ }
+ } else if (inspect->state->exit_code != 0) { // Case 2
+ state = runtime::v1::CONTAINER_EXITED;
+ finishedAt = createdAt;
+ startedAt = createdAt;
+ reason = "ContainerCannotRun";
+ } else { // Case 3
+ state = runtime::v1::CONTAINER_CREATED;
+ }
+ if (inspect->state->error != nullptr) {
+ message = inspect->state->error;
+ }
+ exitCode = (int32_t)inspect->state->exit_code;
+ }
+
+pack_status:
+ contStatus->set_exit_code(exitCode);
+ contStatus->set_state(state);
+ contStatus->set_created_at(createdAt);
+ contStatus->set_started_at(startedAt);
+ contStatus->set_finished_at(finishedAt);
+ contStatus->set_reason(reason);
+ contStatus->set_message(message);
+}
+
+void PackLabelsToStatus(container_inspect *inspect,
+ std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
+{
+ if (inspect->config == nullptr || inspect->config->labels == nullptr) {
+ return;
+ }
+ CRIHelpers::ExtractLabels(inspect->config->labels, *contStatus->mutable_labels());
+ CRIHelpers::ExtractAnnotations(inspect->config->annotations, *contStatus->mutable_annotations());
+ for (size_t i = 0; i < inspect->config->labels->len; i++) {
+ if (strcmp(inspect->config->labels->keys[i], CRIHelpers::Constants::CONTAINER_LOGPATH_LABEL_KEY.c_str()) == 0) {
+ contStatus->set_log_path(inspect->config->labels->values[i]);
+ break;
+ }
+ }
+}
+
+void ConvertMountsToStatus(container_inspect *inspect,
+ std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
+{
+ for (size_t i = 0; i < inspect->mounts_len; i++) {
+ runtime::v1::Mount *mount = contStatus->add_mounts();
+ mount->set_host_path(inspect->mounts[i]->source);
+ mount->set_container_path(inspect->mounts[i]->destination);
+ mount->set_readonly(!inspect->mounts[i]->rw);
+ if (inspect->mounts[i]->propagation == nullptr || strcmp(inspect->mounts[i]->propagation, "rprivate") == 0) {
+ mount->set_propagation(runtime::v1::PROPAGATION_PRIVATE);
+ } else if (strcmp(inspect->mounts[i]->propagation, "rslave") == 0) {
+ mount->set_propagation(runtime::v1::PROPAGATION_HOST_TO_CONTAINER);
+ } else if (strcmp(inspect->mounts[i]->propagation, "rshared") == 0) {
+ mount->set_propagation(runtime::v1::PROPAGATION_BIDIRECTIONAL);
+ }
+ // Note: Can't set SeLinuxRelabel
+ }
+}
+
+void ConvertResourcesToStatus(container_inspect *inspect,
+ std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
+{
+ if (inspect->resources == nullptr) {
+ return;
+ }
+ runtime::v1::LinuxContainerResources *resources = contStatus->mutable_resources()->mutable_linux();
+ if (inspect->resources->cpu_shares != 0) {
+ resources->set_cpu_shares(inspect->resources->cpu_shares);
+ }
+ if (inspect->resources->cpu_period != 0) {
+ resources->set_cpu_period(inspect->resources->cpu_period);
+ }
+ if (inspect->resources->cpu_quota != 0) {
+ resources->set_cpu_quota(inspect->resources->cpu_quota);
+ }
+ if (inspect->resources->memory != 0) {
+ resources->set_memory_limit_in_bytes(inspect->resources->memory);
+ }
+ if (inspect->resources->memory_swap != 0) {
+ resources->set_memory_swap_limit_in_bytes(inspect->resources->memory_swap);
+ }
+ for (size_t i = 0; i < inspect->resources->hugetlbs_len; i++) {
+ runtime::v1::HugepageLimit *hugepage = resources->add_hugepage_limits();
+ hugepage->set_page_size(inspect->resources->hugetlbs[i]->page_size);
+ hugepage->set_limit(inspect->resources->hugetlbs[i]->limit);
+ }
+ if (inspect->resources->unified != nullptr) {
+ for (size_t i = 0; i < inspect->resources->unified->len; i++) {
+ auto &resUnified = *(resources->mutable_unified());
+ resUnified[inspect->resources->unified->keys[i]] = inspect->resources->unified->values[i];
+ }
+ }
+}
+
+void ContainerStatusToGRPC(container_inspect *inspect,
+ std::unique_ptr<runtime::v1::ContainerStatus> &contStatus,
+ Errors &error)
+{
+ if (inspect->id != nullptr) {
+ contStatus->set_id(inspect->id);
+ }
+
+ int64_t createdAt {};
+ int64_t startedAt {};
+ int64_t finishedAt {};
+ CRIHelpers::GetContainerTimeStamps(inspect, &createdAt, &startedAt, &finishedAt, error);
+ if (error.NotEmpty()) {
+ return;
+ }
+ contStatus->set_created_at(createdAt);
+ contStatus->set_started_at(startedAt);
+ contStatus->set_finished_at(finishedAt);
+
+ PackContainerImageToStatus(inspect, contStatus, error);
+ UpdateBaseStatusFromInspect(inspect, createdAt, startedAt, finishedAt, contStatus);
+ PackLabelsToStatus(inspect, contStatus);
+ CRINamingV1::ParseContainerName(contStatus->annotations(), contStatus->mutable_metadata(), error);
+ if (error.NotEmpty()) {
+ return;
+ }
+ ConvertMountsToStatus(inspect, contStatus);
+ ConvertResourcesToStatus(inspect, contStatus);
+}
+
+std::unique_ptr<runtime::v1::ContainerStatus> GetContainerStatus(service_executor_t *m_cb, const std::string &containerID, Errors &error)
+{
+ if (m_cb == nullptr) {
+ error.SetError("Invalid input arguments: empty service executor");
+ return nullptr;
+ }
+
+ if (containerID.empty()) {
+ error.SetError("Empty container id");
+ return nullptr;
+ }
+
+ std::string realContainerID = CRIHelpers::GetRealContainerOrSandboxID(m_cb, containerID, false, error);
+ if (error.NotEmpty()) {
+ ERROR("Failed to find container id %s: %s", containerID.c_str(), error.GetCMessage());
+ error.Errorf("Failed to find container id %s: %s", containerID.c_str(), error.GetCMessage());
+ return nullptr;
+ }
+
+ container_inspect *inspect = CRIHelpers::InspectContainer(realContainerID, error, false);
+ if (error.NotEmpty()) {
+ return nullptr;
+ }
+ if (inspect == nullptr) {
+ error.SetError("Get null inspect");
+ return nullptr;
+ }
+ using ContainerStatusPtr = std::unique_ptr<runtime::v1::ContainerStatus>;
+ ContainerStatusPtr contStatus(new (std::nothrow) runtime::v1::ContainerStatus);
+ if (contStatus == nullptr) {
+ error.SetError("Out of memory");
+ free_container_inspect(inspect);
+ return nullptr;
+ }
+
+ ContainerStatusToGRPC(inspect, contStatus, error);
+
+ free_container_inspect(inspect);
+ return contStatus;
+}
+
} // v1 namespace CRIHelpers
diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.h b/src/daemon/common/cri/v1/v1_cri_helpers.h
index b6e6aec6..1578c428 100644
--- a/src/daemon/common/cri/v1/v1_cri_helpers.h
+++ b/src/daemon/common/cri/v1/v1_cri_helpers.h
@@ -27,6 +27,8 @@
#include "checkpoint_handler.h"
#include "constants.h"
#include "errors.h"
+#include "callback.h"
+#include "cstruct_wrapper.h"
namespace CRIHelpersV1 {
@@ -78,6 +80,9 @@ std::string CRISandboxerConvert(const std::string &runtime);
void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc,
Errors &error);
+auto GetContainerStatus(service_executor_t *m_cb, const std::string &containerID, Errors &error)
+-> std::unique_ptr<runtime::v1::ContainerStatus>;
+
}; // namespace CRIHelpers
#endif // DAEMON_ENTRY_CRI_V1ALPHA_CRI_HELPERS_H
diff --git a/src/daemon/entry/cri/v1/v1_naming.cc b/src/daemon/common/cri/v1/v1_naming.cc
similarity index 100%
rename from src/daemon/entry/cri/v1/v1_naming.cc
rename to src/daemon/common/cri/v1/v1_naming.cc
diff --git a/src/daemon/entry/cri/v1/v1_naming.h b/src/daemon/common/cri/v1/v1_naming.h
similarity index 100%
rename from src/daemon/entry/cri/v1/v1_naming.h
rename to src/daemon/common/cri/v1/v1_naming.h
diff --git a/src/daemon/config/isulad_config.c b/src/daemon/config/isulad_config.c
index 8179558e..778ff921 100644
--- a/src/daemon/config/isulad_config.c
+++ b/src/daemon/config/isulad_config.c
@@ -1760,6 +1760,7 @@ int merge_json_confs_into_global(struct service_arguments *args)
args->json_confs->cri_sandboxers = tmp_json_confs->cri_sandboxers;
tmp_json_confs->cri_sandboxers = NULL;
args->json_confs->enable_cri_v1 = tmp_json_confs->enable_cri_v1;
+ args->json_confs->enable_pod_events = tmp_json_confs->enable_pod_events;
#endif
args->json_confs->systemd_cgroup = tmp_json_confs->systemd_cgroup;
diff --git a/src/daemon/entry/connect/grpc/cri/cri_service.cc b/src/daemon/entry/connect/grpc/cri/cri_service.cc
index c1986c44..d10a60b5 100644
--- a/src/daemon/entry/connect/grpc/cri/cri_service.cc
+++ b/src/daemon/entry/connect/grpc/cri/cri_service.cc
@@ -89,8 +89,9 @@ int CRIService::Init(const isulad_daemon_configs *config)
#ifdef ENABLE_CRI_API_V1
m_enableCRIV1 = config->enable_cri_v1;
+ m_enablePodEvents = config->enable_pod_events;
if (m_enableCRIV1) {
- m_runtimeV1RuntimeService.Init(m_podSandboxImage, m_pluginManager, err);
+ m_runtimeV1RuntimeService.Init(m_podSandboxImage, m_pluginManager, m_enablePodEvents, err);
if (err.NotEmpty()) {
ERROR("Init CRI v1 runtime service failed: %s", err.GetCMessage());
return -1;
diff --git a/src/daemon/entry/connect/grpc/cri/cri_service.h b/src/daemon/entry/connect/grpc/cri/cri_service.h
index 77b2eb72..041c7c63 100644
--- a/src/daemon/entry/connect/grpc/cri/cri_service.h
+++ b/src/daemon/entry/connect/grpc/cri/cri_service.h
@@ -56,6 +56,7 @@ private:
std::string m_podSandboxImage;
std::shared_ptr<Network::PluginManager> m_pluginManager;
bool m_enableCRIV1;
+ bool m_enablePodEvents;
};
}
diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc
index 76e393f3..bc5ab591 100644
--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc
+++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc
@@ -22,11 +22,37 @@
#include "callback.h"
#include "network_plugin.h"
#include "v1_cri_runtime_service_impl.h"
+#include "mailbox.h"
+#include "mailbox_message.h"
using namespace CRIV1;
+static void *cri_container_topic_handler(void *context, void *arg)
+{
+ if (context == nullptr || arg == nullptr) {
+ ERROR("Invalid input arguments");
+ return nullptr;
+ }
+
+ auto v1runtimeService = static_cast<RuntimeV1RuntimeServiceImpl *>(context);
+ auto msg = static_cast<cri_container_message_t *>(arg);
+ return v1runtimeService->GenerateCRIContainerEvent(msg->container_id, msg->sandbox_id,
+ static_cast<runtime::v1::ContainerEventType>(msg->type));
+}
+
+static void cri_container_topic_release(void *arg)
+{
+ if (arg == nullptr) {
+ return;
+ }
+
+ auto resp = static_cast<runtime::v1::ContainerEventResponse *>(arg);
+ delete resp;
+}
+
void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage,
- std::shared_ptr<Network::PluginManager> networkPlugin, Errors &err)
+ std::shared_ptr<Network::PluginManager> networkPlugin,
+ bool enablePodEvents, Errors &err)
{
// Assembly implementation for CRIRuntimeServiceImpl
service_executor_t *cb = get_service_executor();
@@ -36,7 +62,18 @@ void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage,
return;
}
- m_rService = std::unique_ptr<CRIV1::CRIRuntimeService>(new CRIRuntimeServiceImpl(podSandboxImage, cb, networkPlugin));
+ if (enablePodEvents) {
+ if (mailbox_register_topic_handler(MAILBOX_TOPIC_CRI_CONTAINER, cri_container_topic_handler,
+ this, cri_container_topic_release, true) != 0) {
+ ERROR("Failed to register container topic handler");
+ err.SetError("Failed to register container topic handler");
+ return;
+ }
+ m_enablePodEvents = enablePodEvents;
+ }
+
+
+ m_rService = std::unique_ptr<CRIV1::CRIRuntimeService>(new CRIRuntimeServiceImpl(podSandboxImage, cb, networkPlugin, m_enablePodEvents));
}
void RuntimeV1RuntimeServiceImpl::Wait()
@@ -45,6 +82,54 @@ void RuntimeV1RuntimeServiceImpl::Wait()
void RuntimeV1RuntimeServiceImpl::Shutdown()
{
+ mailbox_unregister_topic_handler(MAILBOX_TOPIC_CRI_CONTAINER);
+}
+
+auto RuntimeV1RuntimeServiceImpl::GenerateCRIContainerEvent(const char *container_id, const char *sandbox_id,
+ runtime::v1::ContainerEventType type) -> runtime::v1::ContainerEventResponse *
+{
+ if (container_id == nullptr || sandbox_id == nullptr) {
+ ERROR("Invalid input arguments");
+ return nullptr;
+ }
+
+ if (type < runtime::v1::ContainerEventType::CONTAINER_CREATED_EVENT ||
+ type > runtime::v1::ContainerEventType::CONTAINER_DELETED_EVENT) {
+ ERROR("Invalid container event type %d", type);
+ return nullptr;
+ }
+
+ std::string containerID(container_id), sandboxID(sandbox_id);
+ Errors error;
+ runtime::v1::ContainerEventResponse *response = new (std::nothrow) runtime::v1::ContainerEventResponse();
+ if (response == nullptr) {
+ ERROR("Out of memory");
+ return nullptr;
+ }
+
+ runtime::v1::PodSandboxStatusResponse *statusReply = new (std::nothrow) runtime::v1::PodSandboxStatusResponse();
+ if (statusReply == nullptr) {
+ ERROR("Out of memory");
+ delete response;
+ return nullptr;
+ }
+
+ m_rService->PodSandboxStatus(sandboxID, statusReply, error);
+ if (!error.Empty()) {
+ WARN("Object: CRI, Type: Failed to status pod:%s due to %s", sandboxID.c_str(),
+ error.GetMessage().c_str());
+ } else {
+ *(response->mutable_pod_sandbox_status()) = *(statusReply->mutable_status());
+ for (auto &containerStatus : statusReply->containers_statuses()) {
+ *(response->add_containers_statuses()) = containerStatus;
+ }
+ }
+
+ response->set_container_event_type((runtime::v1::ContainerEventType)type);
+ response->set_container_id(containerID);
+ response->set_created_at(util_get_now_time_nanos());
+
+ return response;
}
grpc::Status RuntimeV1RuntimeServiceImpl::Version(grpc::ServerContext *context,
@@ -398,14 +483,12 @@ grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStatus(grpc::ServerContext *
INFO("Event: {Object: CRI, Type: Status Pod: %s}", request->pod_sandbox_id().c_str());
- std::unique_ptr<runtime::v1::PodSandboxStatus> podStatus;
- podStatus = m_rService->PodSandboxStatus(request->pod_sandbox_id(), error);
- if (!error.Empty() || !podStatus) {
+ m_rService->PodSandboxStatus(request->pod_sandbox_id(), reply, error);
+ if (!error.Empty()) {
ERROR("Object: CRI, Type: Failed to status pod:%s due to %s", request->pod_sandbox_id().c_str(),
error.GetMessage().c_str());
return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage());
}
- *(reply->mutable_status()) = *podStatus;
INFO("Event: {Object: CRI, Type: Statused Pod: %s}", request->pod_sandbox_id().c_str());
@@ -657,3 +740,55 @@ RuntimeV1RuntimeServiceImpl::RuntimeConfig(grpc::ServerContext *context,
return grpc::Status::OK;
}
+
+grpc::Status RuntimeV1RuntimeServiceImpl::GetContainerEvents(grpc::ServerContext *context,
+ const runtime::v1::GetEventsRequest *request,
+ grpc::ServerWriter<runtime::v1::ContainerEventResponse> *writer)
+{
+ Errors error;
+
+ if (context == nullptr || request == nullptr || writer == nullptr) {
+ ERROR("Invalid input arguments");
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid input arguments");
+ }
+
+ if (!m_enablePodEvents) {
+ ERROR("Pod events is not enabled");
+ return grpc::Status(grpc::StatusCode::UNIMPLEMENTED, "Pod events is not enabled");
+ }
+
+ INFO("Event: {Object: CRI, Type: Getting Container Events}");
+
+ __isula_auto_subscriber auto sub = mailbox_subscribe(MAILBOX_TOPIC_CRI_CONTAINER);
+ if (sub == nullptr) {
+ ERROR("Object: CRI, Type: Failed to subscribe container events");
+ return grpc::Status(grpc::StatusCode::UNKNOWN, "Failed to subscribe container events");
+ }
+
+ for (;;) {
+ __isula_auto_mailbox_message mailbox_message *msg = NULL;
+ int ret = message_subscriber_pop(sub, &msg);
+ if (ret == 0) {
+ if (msg == nullptr) {
+ // nullptr response indicates eventqueue being shutdown, not need to unscribe now
+ return grpc::Status(grpc::StatusCode::UNKNOWN, "Event queue is shutdown");
+ }
+ auto *response = static_cast<runtime::v1::ContainerEventResponse *>(msg->data);
+ if (!writer->Write(*response)) {
+ break;
+ }
+ } else if (ret != ETIMEDOUT) {
+ ERROR("Failed to pop message from subscriber");
+ break;
+ }
+ if (context->IsCancelled()) {
+ INFO("Object: CRI, Type: GetContainerEvents is cancelled");
+ break;
+ }
+ }
+
+ mailbox_unsubscribe(MAILBOX_TOPIC_CRI_CONTAINER, sub);
+ INFO("Event: {Object: CRI, Type: Got Container Events}");
+
+ return grpc::Status::OK;
+}
diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h
index 52cc6b99..842d1811 100644
--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h
+++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.h
@@ -26,9 +26,13 @@
// Implement of runtime RuntimeService
class RuntimeV1RuntimeServiceImpl : public runtime::v1::RuntimeService::Service {
public:
- void Init(std::string &podSandboxImage, std::shared_ptr<Network::PluginManager> networkPlugin, Errors &err);
+ void Init(std::string &podSandboxImage, std::shared_ptr<Network::PluginManager> networkPlugin,
+ bool enablePodEvents, Errors &err);
void Wait();
void Shutdown();
+ auto GenerateCRIContainerEvent(const char *container_id, const char *sandbox_id, runtime::v1::ContainerEventType type)
+ -> runtime::v1::ContainerEventResponse *;
+
grpc::Status Version(grpc::ServerContext *context, const runtime::v1::VersionRequest *request,
runtime::v1::VersionResponse *reply) override;
@@ -105,8 +109,13 @@ public:
const runtime::v1::RuntimeConfigRequest *request,
runtime::v1::RuntimeConfigResponse *reply) override;
+ grpc::Status GetContainerEvents(grpc::ServerContext *context,
+ const runtime::v1::GetEventsRequest *request,
+ grpc::ServerWriter<runtime::v1::ContainerEventResponse> *writer) override;
+
private:
std::unique_ptr<CRIV1::CRIRuntimeService> m_rService;
+ bool m_enablePodEvents;
};
#endif // DAEMON_ENTRY_CONNECT_GRPC_CRI_V1_RUNTIME_RUNTIME_SERVICE_H
diff --git a/src/daemon/entry/connect/grpc/grpc_service.cc b/src/daemon/entry/connect/grpc/grpc_service.cc
index 61e284f3..1d8de922 100644
--- a/src/daemon/entry/connect/grpc/grpc_service.cc
+++ b/src/daemon/entry/connect/grpc/grpc_service.cc
@@ -108,11 +108,11 @@ public:
void Shutdown(void)
{
- m_server->Shutdown();
-
- // call CRI to shutdown stream server
+ // call CRI to shutdown stream server, shutdown cri first to notify events thread to exit
m_criService.Shutdown();
+ m_server->Shutdown();
+
// Shutdown daemon, this operation should remove socket file.
for (const auto &address : m_socketPath) {
if (address.find(UNIX_SOCKET_PREFIX) == 0) {
diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
index cac5c0ba..e86dafae 100644
--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
+++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.cc
@@ -1007,208 +1007,9 @@ cleanup:
return contStats;
}
-void ContainerManagerService::PackContainerImageToStatus(
- container_inspect *inspect, std::unique_ptr<runtime::v1::ContainerStatus> &contStatus, Errors &error)
+std::unique_ptr<runtime::v1::ContainerStatus> ContainerManagerService::ContainerStatus(const std::string &containerID, Errors &error)
{
- if (inspect->config == nullptr) {
- return;
- }
-
- if (inspect->config->image != nullptr) {
- contStatus->mutable_image()->set_image(inspect->config->image);
- }
-
- contStatus->set_image_ref(CRIHelpers::ToPullableImageID(inspect->config->image, inspect->config->image_ref));
- return;
-}
-
-void ContainerManagerService::UpdateBaseStatusFromInspect(
- container_inspect *inspect, int64_t &createdAt, int64_t &startedAt, int64_t &finishedAt,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
-{
- runtime::v1::ContainerState state { runtime::v1::CONTAINER_UNKNOWN };
- std::string reason;
- std::string message;
- int32_t exitCode { 0 };
-
- if (inspect->state == nullptr) {
- goto pack_status;
- }
-
- if (inspect->state->running) {
- // Container is running
- state = runtime::v1::CONTAINER_RUNNING;
- } else {
- // Container is not running.
- if (finishedAt != 0) { // Case 1
- state = runtime::v1::CONTAINER_EXITED;
- if (inspect->state->exit_code == 0) {
- reason = "Completed";
- } else {
- reason = "Error";
- }
- } else if (inspect->state->exit_code != 0) { // Case 2
- state = runtime::v1::CONTAINER_EXITED;
- finishedAt = createdAt;
- startedAt = createdAt;
- reason = "ContainerCannotRun";
- } else { // Case 3
- state = runtime::v1::CONTAINER_CREATED;
- }
- if (inspect->state->oom_killed) {
- reason = "OOMKilled";
- }
- if (inspect->state->error != nullptr) {
- message = inspect->state->error;
- }
- exitCode = (int32_t)inspect->state->exit_code;
- }
-
-pack_status:
- contStatus->set_exit_code(exitCode);
- contStatus->set_state(state);
- contStatus->set_created_at(createdAt);
- contStatus->set_started_at(startedAt);
- contStatus->set_finished_at(finishedAt);
- contStatus->set_reason(reason);
- contStatus->set_message(message);
-}
-
-void ContainerManagerService::PackLabelsToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
-{
- if (inspect->config == nullptr || inspect->config->labels == nullptr) {
- return;
- }
- CRIHelpers::ExtractLabels(inspect->config->labels, *contStatus->mutable_labels());
- CRIHelpers::ExtractAnnotations(inspect->config->annotations, *contStatus->mutable_annotations());
- for (size_t i = 0; i < inspect->config->labels->len; i++) {
- if (strcmp(inspect->config->labels->keys[i], CRIHelpers::Constants::CONTAINER_LOGPATH_LABEL_KEY.c_str()) == 0) {
- contStatus->set_log_path(inspect->config->labels->values[i]);
- break;
- }
- }
-}
-
-void ContainerManagerService::ConvertMountsToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
-{
- for (size_t i = 0; i < inspect->mounts_len; i++) {
- runtime::v1::Mount *mount = contStatus->add_mounts();
- mount->set_host_path(inspect->mounts[i]->source);
- mount->set_container_path(inspect->mounts[i]->destination);
- mount->set_readonly(!inspect->mounts[i]->rw);
- if (inspect->mounts[i]->propagation == nullptr || strcmp(inspect->mounts[i]->propagation, "rprivate") == 0) {
- mount->set_propagation(runtime::v1::PROPAGATION_PRIVATE);
- } else if (strcmp(inspect->mounts[i]->propagation, "rslave") == 0) {
- mount->set_propagation(runtime::v1::PROPAGATION_HOST_TO_CONTAINER);
- } else if (strcmp(inspect->mounts[i]->propagation, "rshared") == 0) {
- mount->set_propagation(runtime::v1::PROPAGATION_BIDIRECTIONAL);
- }
- // Note: Can't set SeLinuxRelabel
- }
-}
-
-void ContainerManagerService::ConvertResourcesToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus)
-{
- if (inspect->resources == nullptr) {
- return;
- }
- runtime::v1::LinuxContainerResources *resources = contStatus->mutable_resources()->mutable_linux();
- if (inspect->resources->cpu_shares != 0) {
- resources->set_cpu_shares(inspect->resources->cpu_shares);
- }
- if (inspect->resources->cpu_period != 0) {
- resources->set_cpu_period(inspect->resources->cpu_period);
- }
- if (inspect->resources->cpu_quota != 0) {
- resources->set_cpu_quota(inspect->resources->cpu_quota);
- }
- if (inspect->resources->memory != 0) {
- resources->set_memory_limit_in_bytes(inspect->resources->memory);
- }
- if (inspect->resources->memory_swap != 0) {
- resources->set_memory_swap_limit_in_bytes(inspect->resources->memory_swap);
- }
- for (size_t i = 0; i < inspect->resources->hugetlbs_len; i++) {
- runtime::v1::HugepageLimit *hugepage = resources->add_hugepage_limits();
- hugepage->set_page_size(inspect->resources->hugetlbs[i]->page_size);
- hugepage->set_limit(inspect->resources->hugetlbs[i]->limit);
- }
- if (inspect->resources->unified != nullptr) {
- for (size_t i = 0; i < inspect->resources->unified->len; i++) {
- auto &resUnified = *(resources->mutable_unified());
- resUnified[inspect->resources->unified->keys[i]] = inspect->resources->unified->values[i];
- }
- }
-}
-
-void ContainerManagerService::ContainerStatusToGRPC(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus,
- Errors &error)
-{
- if (inspect->id != nullptr) {
- contStatus->set_id(inspect->id);
- }
-
- int64_t createdAt {};
- int64_t startedAt {};
- int64_t finishedAt {};
- CRIHelpers::GetContainerTimeStamps(inspect, &createdAt, &startedAt, &finishedAt, error);
- if (error.NotEmpty()) {
- return;
- }
- contStatus->set_created_at(createdAt);
- contStatus->set_started_at(startedAt);
- contStatus->set_finished_at(finishedAt);
-
- PackContainerImageToStatus(inspect, contStatus, error);
- UpdateBaseStatusFromInspect(inspect, createdAt, startedAt, finishedAt, contStatus);
- PackLabelsToStatus(inspect, contStatus);
- CRINamingV1::ParseContainerName(contStatus->annotations(), contStatus->mutable_metadata(), error);
- if (error.NotEmpty()) {
- return;
- }
- ConvertMountsToStatus(inspect, contStatus);
- ConvertResourcesToStatus(inspect, contStatus);
-}
-
-std::unique_ptr<runtime::v1::ContainerStatus>
-ContainerManagerService::ContainerStatus(const std::string &containerID, Errors &error)
-{
- if (containerID.empty()) {
- error.SetError("Empty container id");
- return nullptr;
- }
-
- std::string realContainerID = CRIHelpers::GetRealContainerOrSandboxID(m_cb, containerID, false, error);
- if (error.NotEmpty()) {
- ERROR("Failed to find container id %s: %s", containerID.c_str(), error.GetCMessage());
- error.Errorf("Failed to find container id %s: %s", containerID.c_str(), error.GetCMessage());
- return nullptr;
- }
-
- container_inspect *inspect = CRIHelpers::InspectContainer(realContainerID, error, false);
- if (error.NotEmpty()) {
- return nullptr;
- }
- if (inspect == nullptr) {
- error.SetError("Get null inspect");
- return nullptr;
- }
- using ContainerStatusPtr = std::unique_ptr<runtime::v1::ContainerStatus>;
- ContainerStatusPtr contStatus(new (std::nothrow) runtime::v1::ContainerStatus);
- if (contStatus == nullptr) {
- error.SetError("Out of memory");
- free_container_inspect(inspect);
- return nullptr;
- }
-
- ContainerStatusToGRPC(inspect, contStatus, error);
-
- free_container_inspect(inspect);
- return contStatus;
+ return CRIHelpersV1::GetContainerStatus(m_cb, containerID, error);
}
void ContainerManagerService::UpdateContainerResources(const std::string &containerID,
diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h
index 4e772bda..50f5ed69 100644
--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h
+++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h
@@ -111,19 +111,6 @@ private:
std::unique_ptr<runtime::v1::ContainerStats> &container);
void SetFsUsage(const imagetool_fs_info *fs_usage, int64_t timestamp,
std::unique_ptr<runtime::v1::ContainerStats> &container);
- void ContainerStatusToGRPC(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus, Errors &error);
- void PackContainerImageToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus, Errors &error);
- void UpdateBaseStatusFromInspect(container_inspect *inspect, int64_t &createdAt, int64_t &startedAt,
- int64_t &finishedAt,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus);
- void PackLabelsToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus);
- void ConvertMountsToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus);
- void ConvertResourcesToStatus(container_inspect *inspect,
- std::unique_ptr<runtime::v1::ContainerStatus> &contStatus);
void ExecSyncFromGRPC(const std::string &containerID, const google::protobuf::RepeatedPtrField<std::string> &cmd,
int64_t timeout, container_exec_request **request, Errors &error);
auto ValidateExecRequest(const runtime::v1::ExecRequest &req, Errors &error) -> int;
diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
index f125e714..4291d8a0 100644
--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
+++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc
@@ -36,6 +36,7 @@
#include "sandbox_manager.h"
#include "transform.h"
#include "isulad_config.h"
+#include "mailbox.h"
namespace CRIV1 {
void PodSandboxManagerService::PrepareSandboxData(const runtime::v1::PodSandboxConfig &config,
@@ -302,6 +303,7 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig
std::string jsonCheckpoint;
std::string network_setting_json;
runtime::v1::PodSandboxConfig copyConfig = config;
+ cri_container_message_t msg = { 0 };
// Step 1: Parepare sandbox name, runtime and networkMode
PrepareSandboxData(config, runtimeHandler, sandboxName, runtimeInfo, networkMode, error);
@@ -372,6 +374,11 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig
goto cleanup_network;
}
+ msg.container_id = sandbox->GetId().c_str();
+ msg.sandbox_id = sandbox->GetId().c_str();
+ msg.type = CRI_CONTAINER_MESSAGE_TYPE_CREATED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &msg);
+
// Step 10: Save network settings json to disk
// Update network settings before start sandbox since sandbox container will use the sandbox key
if (namespace_is_cni(networkMode.c_str())) {
@@ -391,6 +398,9 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig
return response_id;
}
+ msg.type = CRI_CONTAINER_MESSAGE_TYPE_STARTED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &msg);
+
return sandbox->GetId();
cleanup_network:
@@ -700,6 +710,13 @@ void PodSandboxManagerService::RemovePodSandbox(const std::string &podSandboxID,
ERROR("Failed to delete sandbox %s: %s", podSandboxID.c_str(), error.GetCMessage());
}
+ if (error.Empty()) {
+ cri_container_message_t msg = { 0 };
+ msg.container_id = sandbox->GetId().c_str();
+ msg.sandbox_id = sandbox->GetId().c_str();
+ msg.type = CRI_CONTAINER_MESSAGE_TYPE_DELETED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &msg);
+ }
}
auto PodSandboxManagerService::SharesHostNetwork(const container_inspect *inspect) -> runtime::v1::NamespaceMode
@@ -800,10 +817,29 @@ void PodSandboxManagerService::SetSandboxStatusNetwork(std::shared_ptr<sandbox::
}
}
-std::unique_ptr<runtime::v1::PodSandboxStatus>
-PodSandboxManagerService::PodSandboxStatus(const std::string &podSandboxID, Errors &error)
+void PodSandboxManagerService::GetContainerStatuses(const std::string &podSandboxID,
+ std::vector<std::unique_ptr<runtime::v1::ContainerStatus>> &containerStatuses,
+ std::vector<std::string> &errors) {
+ auto list_response_wrapper = GetContainerListResponse(podSandboxID, errors);
+ if (list_response_wrapper == nullptr) {
+ return;
+ }
+
+ auto list_response = list_response_wrapper->get();
+ // Remove all containers in the sandbox.
+ for (size_t i = 0; i < list_response->containers_len; i++) {
+ Errors stError;
+ containerStatuses.push_back(CRIHelpersV1::GetContainerStatus(m_cb, list_response->containers[i]->id, stError));
+ if (stError.NotEmpty()) {
+ ERROR("Error get container status: %s: %s", list_response->containers[i]->id, stError.GetCMessage());
+ errors.push_back(stError.GetMessage());
+ }
+ }
+}
+
+std::unique_ptr<runtime::v1::PodSandboxStatus> PodSandboxManagerService::GetPodSandboxStatus(const std::string &podSandboxID, Errors &error)
{
- std::unique_ptr<runtime::v1::PodSandboxStatus> podStatus(new runtime::v1::PodSandboxStatus);
+ std::unique_ptr<runtime::v1::PodSandboxStatus> podStatus(new (std::nothrow) runtime::v1::PodSandboxStatus);
if (podStatus == nullptr) {
ERROR("Out of memory");
error.SetError("Out of memory");
@@ -831,6 +867,50 @@ PodSandboxManagerService::PodSandboxStatus(const std::string &podSandboxID, Erro
return podStatus;
}
+void PodSandboxManagerService::PodSandboxStatus(const std::string &podSandboxID,
+ runtime::v1::PodSandboxStatusResponse *reply, Errors &error)
+{
+ if (reply == nullptr) {
+ ERROR("Invalid NULL reply");
+ error.SetError("Invalid NULL reply");
+ return;
+ }
+
+
+ auto podStatus = GetPodSandboxStatus(podSandboxID, error);
+ if (error.NotEmpty()) {
+ ERROR("Failed to get pod sandbox status: %s", error.GetCMessage());
+ return;
+ }
+
+ auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(podSandboxID);
+ if (sandbox == nullptr) {
+ ERROR("Failed to find sandbox id %s", podSandboxID.c_str());
+ error.Errorf("Failed to find sandbox id %s", podSandboxID.c_str());
+ return;
+ }
+
+ *(reply->mutable_status()) = *podStatus;
+
+
+ if (!m_enablePodEvents) {
+ return;
+ }
+
+ std::vector<std::unique_ptr<runtime::v1::ContainerStatus>> containerStatuses;
+ std::vector<std::string> errors;
+ GetContainerStatuses(sandbox->GetId(), containerStatuses, errors);
+ if (errors.size() != 0) {
+ error.SetAggregate(errors);
+ return;
+ }
+
+ for (auto &containerStatus : containerStatuses) {
+ *(reply->add_containers_statuses()) = *containerStatus;
+ }
+ return;
+}
+
void PodSandboxManagerService::ListPodSandbox(const runtime::v1::PodSandboxFilter &filter,
std::vector<std::unique_ptr<runtime::v1::PodSandbox>> &pods,
Errors &error)
@@ -944,7 +1024,7 @@ void PodSandboxManagerService::GetPodSandboxNetworkMetrics(const std::string &ne
void PodSandboxManagerService::PackagePodSandboxStatsAttributes(
const std::string &id, std::unique_ptr<runtime::v1::PodSandboxStats> &podStatsPtr, Errors &error)
{
- auto status = PodSandboxStatus(id, error);
+ auto status = GetPodSandboxStatus(id, error);
if (error.NotEmpty()) {
return;
}
@@ -1111,8 +1191,8 @@ auto PodSandboxManagerService::PodSandboxStats(const std::string &podSandboxID,
auto &config = sandbox->GetSandboxConfig();
auto oldStatsRec = sandbox->GetStatsInfo();
- auto status = PodSandboxStatus(sandbox->GetId(), tmpErr);
- if (error.NotEmpty()) {
+ auto status = GetPodSandboxStatus(sandbox->GetId(), tmpErr);
+ if (tmpErr.NotEmpty()) {
ERROR("Failed to get podsandbox %s status: %s", sandbox->GetId().c_str(), tmpErr.GetCMessage());
error.Errorf("Failed to get podsandbox %s status", sandbox->GetId().c_str());
return nullptr;
diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h
index c3d98b8c..3872c4c9 100644
--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h
+++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h
@@ -38,10 +38,11 @@ namespace CRIV1 {
class PodSandboxManagerService {
public:
PodSandboxManagerService(const std::string &podSandboxImage, service_executor_t *cb,
- std::shared_ptr<Network::PluginManager> pluginManager)
+ std::shared_ptr<Network::PluginManager> pluginManager, bool enablePodEvents)
: m_podSandboxImage(podSandboxImage)
, m_cb(cb)
, m_pluginManager(pluginManager)
+ , m_enablePodEvents(enablePodEvents)
{
}
PodSandboxManagerService(const PodSandboxManagerService &) = delete;
@@ -55,8 +56,7 @@ public:
void RemovePodSandbox(const std::string &podSandboxID, Errors &error);
- auto PodSandboxStatus(const std::string &podSandboxID, Errors &error)
- -> std::unique_ptr<runtime::v1::PodSandboxStatus>;
+ void PodSandboxStatus(const std::string &podSandboxID, runtime::v1::PodSandboxStatusResponse *reply, Errors &error);
void ListPodSandbox(const runtime::v1::PodSandboxFilter &filter,
std::vector<std::unique_ptr<runtime::v1::PodSandbox>> &pods, Errors &error);
@@ -129,6 +129,9 @@ private:
std::vector<std::string> &podSandboxIDs, Errors &error);
void ApplySandboxLinuxOptions(const runtime::v1::LinuxPodSandboxConfig &lc, host_config *hc,
container_config *custom_config, Errors &error);
+ auto GetPodSandboxStatus(const std::string &podSandboxID, Errors &error) -> std::unique_ptr<runtime::v1::PodSandboxStatus>;
+ void GetContainerStatuses(const std::string &podSandboxID, std::vector<std::unique_ptr<runtime::v1::ContainerStatus>> &containerStatuses,
+ std::vector<std::string> &errors);
private:
std::string m_podSandboxImage;
@@ -136,6 +139,7 @@ private:
std::map<std::string, bool> m_networkReady;
service_executor_t *m_cb { nullptr };
std::shared_ptr<Network::PluginManager> m_pluginManager { nullptr };
+ bool m_enablePodEvents;
};
} // namespace CRI
diff --git a/src/daemon/entry/cri/v1/v1_cri_runtime_service.h b/src/daemon/entry/cri/v1/v1_cri_runtime_service.h
index 839f6724..4521e3df 100644
--- a/src/daemon/entry/cri/v1/v1_cri_runtime_service.h
+++ b/src/daemon/entry/cri/v1/v1_cri_runtime_service.h
@@ -70,8 +70,8 @@ public:
virtual void RemovePodSandbox(const std::string &podSandboxID, Errors &error) = 0;
- virtual auto PodSandboxStatus(const std::string &podSandboxID,
- Errors &error) -> std::unique_ptr<runtime::v1::PodSandboxStatus> = 0;
+ virtual void PodSandboxStatus(const std::string &podSandboxID, runtime::v1::PodSandboxStatusResponse *reply,
+ Errors &error) = 0;
virtual void ListPodSandbox(const runtime::v1::PodSandboxFilter &filter,
std::vector<std::unique_ptr<runtime::v1::PodSandbox>> &pods, Errors &error) = 0;
diff --git a/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.cc b/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.cc
index aa5ae516..7b40e29d 100644
--- a/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.cc
+++ b/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.cc
@@ -19,11 +19,12 @@
namespace CRIV1 {
CRIRuntimeServiceImpl::CRIRuntimeServiceImpl(const std::string &podSandboxImage, service_executor_t *cb,
- std::shared_ptr<Network::PluginManager> pluginManager)
+ std::shared_ptr<Network::PluginManager> pluginManager, bool enablePodEvents)
: m_runtimeVersioner(new RuntimeVersionerService(cb))
, m_containerManager(new ContainerManagerService(cb))
- , m_podSandboxManager(new PodSandboxManagerService(podSandboxImage, cb, pluginManager))
+ , m_podSandboxManager(new PodSandboxManagerService(podSandboxImage, cb, pluginManager, enablePodEvents))
, m_runtimeManager(new RuntimeManagerService(cb, pluginManager))
+ , m_enablePodEvents(enablePodEvents)
{
}
@@ -124,10 +125,9 @@ void CRIRuntimeServiceImpl::RemovePodSandbox(const std::string &podSandboxID, Er
m_podSandboxManager->RemovePodSandbox(podSandboxID, error);
}
-auto CRIRuntimeServiceImpl::PodSandboxStatus(const std::string &podSandboxID, Errors &error)
--> std::unique_ptr<runtime::v1::PodSandboxStatus>
+void CRIRuntimeServiceImpl::PodSandboxStatus(const std::string &podSandboxID, runtime::v1::PodSandboxStatusResponse *reply, Errors &error)
{
- return m_podSandboxManager->PodSandboxStatus(podSandboxID, error);
+ m_podSandboxManager->PodSandboxStatus(podSandboxID, reply, error);
}
void CRIRuntimeServiceImpl::ListPodSandbox(const runtime::v1::PodSandboxFilter &filter,
diff --git a/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.h b/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.h
index 0a25749f..6ae59bfa 100644
--- a/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.h
+++ b/src/daemon/entry/cri/v1/v1_cri_runtime_service_impl.h
@@ -26,7 +26,8 @@ namespace CRIV1 {
class CRIRuntimeServiceImpl : public CRIRuntimeService {
public:
CRIRuntimeServiceImpl(const std::string &podSandboxImage, service_executor_t *cb,
- std::shared_ptr<Network::PluginManager> pluginManager);
+ std::shared_ptr<Network::PluginManager> pluginManager,
+ bool enablePodEvents);
CRIRuntimeServiceImpl(const CRIRuntimeServiceImpl &) = delete;
auto operator=(const CRIRuntimeServiceImpl &) -> CRIRuntimeServiceImpl & = delete;
virtual ~CRIRuntimeServiceImpl() = default;
@@ -72,8 +73,7 @@ public:
void RemovePodSandbox(const std::string &podSandboxID, Errors &error) override;
- auto PodSandboxStatus(const std::string &podSandboxID, Errors &error)
- -> std::unique_ptr<runtime::v1::PodSandboxStatus> override;
+ void PodSandboxStatus(const std::string &podSandboxID, runtime::v1::PodSandboxStatusResponse *reply, Errors &error) override;
void ListPodSandbox(const runtime::v1::PodSandboxFilter &filter,
std::vector<std::unique_ptr<runtime::v1::PodSandbox>> &pods, Errors &error) override;
@@ -103,6 +103,7 @@ protected:
private:
std::string m_podSandboxImage;
std::shared_ptr<Network::PluginManager> m_pluginManager { nullptr };
+ bool m_enablePodEvents;
};
} // namespace CRIV1
#endif // DAEMON_ENTRY_CRI_V1_CRI_RUNTIME_SERVICE_IMPL_H
diff --git a/src/daemon/executor/container_cb/execution.c b/src/daemon/executor/container_cb/execution.c
index 88c6b354..e5c96628 100644
--- a/src/daemon/executor/container_cb/execution.c
+++ b/src/daemon/executor/container_cb/execution.c
@@ -62,6 +62,7 @@
#include "event_type.h"
#include "utils_timestamp.h"
#include "utils_verify.h"
+#include "mailbox.h"
#ifdef ENABLE_NATIVE_NETWORK
#include "service_network_api.h"
@@ -542,6 +543,9 @@ static int container_start_cb(const container_start_request *request, container_
container_t *cont = NULL;
int sync_fd = -1;
pthread_t thread_id = 0;
+#ifdef ENABLE_CRI_API_V1
+ cri_container_message_t message;
+#endif
DAEMON_CLEAR_ERRMSG();
@@ -596,6 +600,15 @@ static int container_start_cb(const container_start_request *request, container_
EVENT("Event: {Object: %s, Type: Running}", id);
(void)isulad_monitor_send_container_event(id, START, -1, 0, NULL, NULL);
+#ifdef ENABLE_CRI_API_V1
+ if (is_container_in_sandbox(cont->common_config->sandbox_info)) {
+ message.container_id = id;
+ message.sandbox_id = cont->common_config->sandbox_info->id;
+ message.type = CRI_CONTAINER_MESSAGE_TYPE_STARTED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &message);
+ }
+#endif
+
pack_response:
handle_start_io_thread_by_cc(cc, sync_fd, thread_id);
delete_daemon_fifos(fifopath, (const char **)fifos);
@@ -1009,6 +1022,9 @@ static int container_delete_cb(const container_delete_request *request, containe
char *name = NULL;
char *id = NULL;
container_t *cont = NULL;
+#ifdef ENABLE_CRI_API_V1
+ cri_container_message_t message;
+#endif
DAEMON_CLEAR_ERRMSG();
if (request == NULL || response == NULL) {
@@ -1063,6 +1079,15 @@ static int container_delete_cb(const container_delete_request *request, containe
EVENT("Event: {Object: %s, Type: Deleted}", id);
+#ifdef ENABLE_CRI_API_V1
+ if (is_container_in_sandbox(cont->common_config->sandbox_info)) {
+ message.container_id = cont->common_config->id;
+ message.sandbox_id = cont->common_config->sandbox_info->id;
+ message.type = CRI_CONTAINER_MESSAGE_TYPE_DELETED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &message);
+ }
+#endif
+
pack_response:
pack_delete_response(*response, cc, id);
container_unref(cont);
diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c
index e00afb68..a9102226 100644
--- a/src/daemon/executor/container_cb/execution_create.c
+++ b/src/daemon/executor/container_cb/execution_create.c
@@ -62,6 +62,7 @@
#include "opt_log.h"
#include "runtime_api.h"
#include "id_name_manager.h"
+#include "mailbox.h"
#ifdef ENABLE_CRI_API_V1
static bool validate_sandbox_info(const container_sandbox_info *sandbox)
@@ -1389,6 +1390,9 @@ int container_create_cb(const container_create_request *request, container_creat
bool skip_id_name_manage = false;
bool skip_sandbox_key_manage = false;
__isula_auto_sysinfo_t sysinfo_t *sysinfo = NULL;
+#ifdef ENABLE_CRI_API_V1
+ cri_container_message_t message;
+#endif
DAEMON_CLEAR_ERRMSG();
@@ -1572,6 +1576,14 @@ int container_create_cb(const container_create_request *request, container_creat
EVENT("Event: {Object: %s, Type: Created %s}", id, name);
(void)isulad_monitor_send_container_event(id, CREATE, -1, 0, NULL, NULL);
+#ifdef ENABLE_CRI_API_V1
+ if (is_container_in_sandbox(request->sandbox)) {
+ message.container_id = id;
+ message.sandbox_id = request->sandbox->id;
+ message.type = CRI_CONTAINER_MESSAGE_TYPE_CREATED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &message);
+ }
+#endif
goto pack_response;
umount_channel:
diff --git a/src/daemon/mailbox/CMakeLists.txt b/src/daemon/mailbox/CMakeLists.txt
new file mode 100644
index 00000000..984f9acb
--- /dev/null
+++ b/src/daemon/mailbox/CMakeLists.txt
@@ -0,0 +1,11 @@
+# get current directory sources files
+aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} mailbox_top_srcs)
+
+set(MAILBOX_SRCS
+ ${mailbox_top_srcs}
+ PARENT_SCOPE
+ )
+set(MAILBOX_INCS
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ PARENT_SCOPE
+ )
\ No newline at end of file
diff --git a/src/daemon/mailbox/mailbox.c b/src/daemon/mailbox/mailbox.c
new file mode 100644
index 00000000..732b91b9
--- /dev/null
+++ b/src/daemon/mailbox/mailbox.c
@@ -0,0 +1,167 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide common event definition
+ ******************************************************************************/
+
+#include "mailbox.h"
+
+#include <isula_libutils/log.h>
+
+#include "message_queue.h"
+#include "mailbox_message.h"
+#include "message_subscriber.h"
+
+mailbox_topic_handler_t mailbox_topic_handlers[MAILBOX_TOPIC_MAX] = { 0 };
+
+static bool mailbox_topic_valid(mailbox_topic topic) {
+ return topic > MAILBOX_TOPIC_INVALID && topic < MAILBOX_TOPIC_MAX;
+}
+
+static bool mailbox_should_publish(mailbox_topic topic)
+{
+ if (!mailbox_topic_valid(topic)) {
+ ERROR("Invalid topic %d", topic);
+ return false;
+ }
+
+ if (!mailbox_topic_handlers[topic].registered) {
+ return false;
+ }
+
+ if (mailbox_topic_handlers[topic].queue == NULL) {
+ return true;
+ }
+
+ // for async queues, only publish if anyone subscribe
+ return message_queue_have_subscribers(mailbox_topic_handlers[topic].queue);
+}
+
+// only register once when iSulad start, no need to free the queue
+int mailbox_register_topic_handler(mailbox_topic topic, message_generator_t generator, void *context,
+ message_release_t release, bool async)
+{
+ if (!mailbox_topic_valid(topic)) {
+ ERROR("Invalid topic %d", topic);
+ return -1;
+ }
+
+ if (generator == NULL) {
+ ERROR("Invalid generator for topic %d", topic);
+ return -1;
+ }
+
+ mailbox_topic_handlers[topic].generator = generator;
+ mailbox_topic_handlers[topic].context = context;
+ mailbox_topic_handlers[topic].release = release;
+ if (async) {
+ mailbox_topic_handlers[topic].queue = message_queue_create(release);
+ if (mailbox_topic_handlers[topic].queue == NULL) {
+ ERROR("Failed to create message queue for topic %d", topic);
+ return -1;
+ }
+ }
+ mailbox_topic_handlers[topic].registered = true;
+ return 0;
+}
+
+// unregister only when iSulad shutdown, no need to free the queue
+void mailbox_unregister_topic_handler(mailbox_topic topic)
+{
+ if (!mailbox_topic_valid(topic)) {
+ ERROR("Invalid topic %d", topic);
+ return;
+ }
+
+ if (mailbox_topic_handlers[topic].queue != NULL) {
+ message_queue_shutdown(mailbox_topic_handlers[topic].queue);
+ }
+ mailbox_topic_handlers[topic].registered = false;
+}
+
+void mailbox_publish(mailbox_topic topic, void *data)
+{
+ if (!mailbox_should_publish(topic)) {
+ return;
+ }
+
+ message_generator_t generator = mailbox_topic_handlers[topic].generator;
+ void *context = mailbox_topic_handlers[topic].context;
+ message_release_t release = mailbox_topic_handlers[topic].release;
+ message_queue *queue = mailbox_topic_handlers[topic].queue;
+
+ if (generator == NULL) {
+ ERROR("No handler for topic %d", topic);
+ return;
+ }
+
+ void *middle = generator(context, data);
+ if (middle == NULL) {
+ return;
+ }
+
+ if (queue != NULL) {
+ mailbox_message *msg = mailbox_message_create(middle, release);
+ if (msg == NULL) {
+ ERROR("Failed to create mailbox message");
+ if (release) {
+ release(middle);
+ }
+ return;
+ }
+ if (message_queue_publish(queue, msg) != 0) {
+ ERROR("Failed to publish event");
+ mailbox_message_unref(msg);
+ return;
+ }
+ }
+}
+
+message_subscriber *mailbox_subscribe(mailbox_topic topic)
+{
+ if (!mailbox_topic_valid(topic)) {
+ ERROR("Invalid topic %d", topic);
+ return NULL;
+ }
+
+ if (!mailbox_topic_handlers[topic].registered) {
+ ERROR("Handler for topic %d not registered", topic);
+ return NULL;
+ }
+
+ if (mailbox_topic_handlers[topic].queue != NULL) {
+ return message_queue_subscribe(mailbox_topic_handlers[topic].queue,
+ mailbox_topic_handlers[topic].release);
+ }
+
+ // For sync queues, there is no need to subscribe, just return
+ return NULL;
+}
+
+void mailbox_unsubscribe(mailbox_topic topic, message_subscriber *sub)
+{
+ if (!mailbox_topic_valid(topic)) {
+ ERROR("Invalid topic %d", topic);
+ return;
+ }
+
+ if (!mailbox_topic_handlers[topic].registered) {
+ ERROR("Handler for topic %d not registered", topic);
+ return;
+ }
+
+ if (mailbox_topic_handlers[topic].queue != NULL) {
+ return message_queue_unsubscribe(mailbox_topic_handlers[topic].queue, sub);
+ }
+
+ return;
+}
diff --git a/src/daemon/mailbox/mailbox.h b/src/daemon/mailbox/mailbox.h
new file mode 100644
index 00000000..1dc2e934
--- /dev/null
+++ b/src/daemon/mailbox/mailbox.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide common event definition
+ ******************************************************************************/
+
+#ifndef DAEMON_MAILBOX_MAILBOX_H
+#define DAEMON_MAILBOX_MAILBOX_H
+
+#include "daemon_arguments.h"
+#include "blocking_queue.h"
+#include "message_queue.h"
+#include "message_subscriber.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef enum {
+ MAILBOX_TOPIC_INVALID = -1,
+ MAILBOX_TOPIC_CRI_CONTAINER,
+ MAILBOX_TOPIC_MAX
+} mailbox_topic;
+
+// for async message, it generates a true message to publish
+// for sync message, it is the callback function to handle the data to publish
+typedef void *(*message_generator_t)(void *, void *);
+// release function of message generated by generator, if any
+typedef void (*message_release_t)(void *);
+
+typedef struct {
+ // to generate a message
+ message_generator_t generator;
+ // context of handler
+ void *context;
+ // release function of message, if any
+ message_release_t release;
+ // message queue
+ message_queue *queue;
+ // if registered
+ bool registered;
+} mailbox_topic_handler_t;
+
+typedef enum {
+ CRI_CONTAINER_MESSAGE_TYPE_INVALID = -1,
+ CRI_CONTAINER_MESSAGE_TYPE_CREATED,
+ CRI_CONTAINER_MESSAGE_TYPE_STARTED,
+ CRI_CONTAINER_MESSAGE_TYPE_STOPPED,
+ CRI_CONTAINER_MESSAGE_TYPE_DELETED,
+ CRI_CONTAINER_MESSAGE_TYPE_MAX
+} cri_container_message_type;
+
+typedef struct {
+ const char *container_id;
+ const char *sandbox_id;
+ cri_container_message_type type;
+} cri_container_message_t;
+
+int mailbox_register_topic_handler(mailbox_topic topic, message_generator_t handle, void *context,
+ message_release_t release, bool async);
+
+void mailbox_unregister_topic_handler(mailbox_topic topic);
+
+void mailbox_publish(mailbox_topic topic, void *data);
+
+message_subscriber *mailbox_subscribe(mailbox_topic topic);
+
+void mailbox_unsubscribe(mailbox_topic, message_subscriber *sub);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/daemon/mailbox/mailbox_message.c b/src/daemon/mailbox/mailbox_message.c
new file mode 100644
index 00000000..b16a1bdd
--- /dev/null
+++ b/src/daemon/mailbox/mailbox_message.c
@@ -0,0 +1,94 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide mailbox message definition
+ ******************************************************************************/
+
+#include "mailbox_message.h"
+
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+
+// Once the create succeeds, the ownership is transferred to the mailbox_message.
+mailbox_message *mailbox_message_create(void *data, void (*destroy)(void *)) {
+ __isula_auto_free mailbox_message *msg = NULL;
+ msg = util_common_calloc_s(sizeof(mailbox_message));
+ if (msg == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ msg->data = data;
+ msg->destroy = destroy;
+ msg->ref_count = 1;
+
+ if (pthread_mutex_init(&msg->lock, NULL) != 0) {
+ ERROR("Failed to init mutex");
+ return NULL;
+ }
+
+ return isula_transfer_ptr(msg);
+}
+
+int mailbox_message_ref(mailbox_message *dest) {
+ __isula_auto_pm_unlock pthread_mutex_t *lock = NULL;
+ if (dest == NULL) {
+ ERROR("Invalid mailbox_message");
+ return -1;
+ }
+
+ if (pthread_mutex_lock(&dest->lock) != 0) {
+ ERROR("Failed to lock mutex");
+ return -1;
+ }
+ lock = &dest->lock;
+
+ if (dest->ref_count == INT_MAX) {
+ ERROR("Reference count overflow");
+ return -1;
+ }
+
+ dest->ref_count++;
+
+ return 0;
+}
+
+void mailbox_message_unref(mailbox_message *dest) {
+ __isula_auto_pm_unlock pthread_mutex_t *lock = NULL;
+ if (dest == NULL) {
+ return;
+ }
+
+ if (pthread_mutex_lock(&dest->lock) != 0) {
+ ERROR("Failed to lock mutex");
+ return;
+ }
+ lock = &dest->lock;
+
+ if (dest->ref_count == 0) {
+ ERROR("Reference count underflow, should not reach here");
+ return;
+ }
+
+ dest->ref_count--;
+ if (dest->ref_count == 0) {
+ if (dest->destroy) {
+ dest->destroy(dest->data);
+ }
+ lock = NULL;
+ (void)pthread_mutex_unlock(&dest->lock);
+ (void)pthread_mutex_destroy(&dest->lock);
+ free(dest);
+ }
+ return;
+}
diff --git a/src/daemon/mailbox/mailbox_message.h b/src/daemon/mailbox/mailbox_message.h
new file mode 100644
index 00000000..39e40b70
--- /dev/null
+++ b/src/daemon/mailbox/mailbox_message.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide ref counted ptr definition
+ ******************************************************************************/
+
+#ifndef DAEMON_MAILBOX_MAILBOX_MESSAGE_H
+#define DAEMON_MAILBOX_MAILBOX_MESSAGE_H
+
+#include <pthread.h>
+#include <stdbool.h>
+
+#include <isula_libutils/auto_cleanup.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct mailbox_message {
+ void *data;
+ size_t ref_count;
+ pthread_mutex_t lock;
+ void (*destroy)(void *);
+} mailbox_message;
+
+mailbox_message *mailbox_message_create(void *ptr, void (*destroy)(void *));
+
+int mailbox_message_ref(mailbox_message *p);
+
+void mailbox_message_unref(mailbox_message *p);
+
+// define auto free function callback for mailbox_message
+define_auto_cleanup_callback(mailbox_message_unref, mailbox_message);
+// define auto free macro for char *
+#define __isula_auto_mailbox_message auto_cleanup_tag(mailbox_message_unref)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/daemon/mailbox/message_queue.c b/src/daemon/mailbox/message_queue.c
new file mode 100644
index 00000000..7fe044f2
--- /dev/null
+++ b/src/daemon/mailbox/message_queue.c
@@ -0,0 +1,234 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide message queue definition
+ ******************************************************************************/
+
+#include "message_queue.h"
+
+#include <sys/prctl.h>
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+
+// default set subscriber timeout to 1000ms, maybe could be configured later
+const int64_t subscribe_timeout = 1000;
+
+static void message_queue_subscriber_free(void *key, void *val)
+{
+ return;
+}
+
+static void *message_queue_thread(void *arg)
+{
+ int ret = 0;
+
+ ret = pthread_detach(pthread_self());
+ if (ret != 0) {
+ CRIT("Set thread detach fail");
+ return NULL;
+ }
+
+ prctl(PR_SET_NAME, "Message Queue");
+
+ message_queue *mq = (message_queue *)arg;
+ if (mq == NULL) {
+ ERROR("Invalid argument");
+ return NULL;
+ }
+
+ for (;;) {
+ void *data = NULL;
+ if (blocking_queue_pop(mq->messages, &data) != 0) {
+ ERROR("Fail to get message, message queue thread exit");
+ break;
+ }
+
+ __isula_auto_mailbox_message mailbox_message *msg = (mailbox_message *)data;
+ // an empty msg indicates shutdown
+ if (pthread_rwlock_rdlock(&mq->rwlock) != 0) {
+ ERROR("Failed to lock rwlock");
+ continue;
+ }
+
+ bool should_shutdown = (msg == NULL);
+ map_itor *itor = map_itor_new(mq->subscribers);
+ if (itor == NULL) {
+ ERROR("Out of memory");
+ if (pthread_rwlock_unlock(&mq->rwlock) != 0) {
+ ERROR("Failed to lock rwlock");
+ }
+ break;
+ }
+
+ for (; map_itor_valid(itor); map_itor_next(itor)) {
+ void *sub = map_itor_key(itor);
+ if (should_shutdown) {
+ message_subscriber_shutdown(sub);
+ } else {
+ if (message_subscriber_push(sub, msg) != 0) {
+ ERROR("Failed to push event to subscriber");
+ }
+ }
+ }
+ map_itor_free(itor);
+
+ if (pthread_rwlock_unlock(&mq->rwlock) != 0) {
+ ERROR("Failed to unlock rwlock");
+ }
+
+ // if msg is NULL, it is a shutdown signal
+ if (should_shutdown) {
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+message_queue *message_queue_create(void (*release)(void *))
+{
+ __isula_auto_free message_queue *mq = NULL;
+ __isula_auto_blocking_queue blocking_queue *bq = NULL;
+ pthread_t message_queue_tid;
+ mq = util_common_calloc_s(sizeof(message_queue));
+ if (mq == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ bq = blocking_queue_create(BLOCKING_QUEUE_NO_TIMEOUT, release);
+ if (bq == NULL) {
+ ERROR("Failed to create events queue");
+ return NULL;
+ }
+
+ mq->subscribers = map_new(MAP_PTR_INT, MAP_DEFAULT_CMP_FUNC, message_queue_subscriber_free);
+ if (mq->subscribers == NULL) {
+ ERROR("Failed to create subscribers map");
+ return NULL;
+ }
+
+ if (pthread_rwlock_init(&mq->rwlock, NULL) != 0) {
+ ERROR("Failed to init rwlock");
+ map_free(mq->subscribers);
+ return NULL;
+ }
+
+ if (pthread_create(&message_queue_tid, NULL, message_queue_thread, mq) != 0) {
+ ERROR("Failed to create message queue thread");
+ pthread_rwlock_destroy(&mq->rwlock);
+ map_free(mq->subscribers);
+ return NULL;
+ }
+
+ mq->messages = isula_transfer_ptr(bq);
+ return isula_transfer_ptr(mq);
+}
+
+// message queue should be global value, it will be destroyed when daemon exit
+void message_queue_shutdown(message_queue *mq)
+{
+ if (mq == NULL) {
+ return;
+ }
+
+ blocking_queue_clear(mq->messages);
+
+ // push a nullptr to notify the thread to exit
+ if (blocking_queue_push(mq->messages, NULL) != 0) {
+ ERROR("Failed to push nullptr to message queue");
+ }
+}
+
+message_subscriber *message_queue_subscribe(message_queue *mq, void (*release)(void *))
+{
+ __isula_auto_subscriber message_subscriber *sub = NULL;
+ __isula_auto_prw_unlock pthread_rwlock_t *lock = NULL;
+ int val = 0;
+ if (mq == NULL) {
+ ERROR("Invalid argument");
+ return NULL;
+ }
+
+ sub = message_subscriber_create(subscribe_timeout, release);
+ if (sub == NULL) {
+ ERROR("Failed to create subscriber");
+ return NULL;
+ }
+
+ if (pthread_rwlock_wrlock(&mq->rwlock) != 0) {
+ ERROR("Failed to lock rwlock");
+ return NULL;
+ }
+ lock = &mq->rwlock;
+
+ if (map_insert(mq->subscribers, sub, (void *)&val) == false) {
+ ERROR("Failed to insert subscriber");
+ return NULL;
+ }
+
+ return isula_transfer_ptr(sub);
+}
+
+void message_queue_unsubscribe(message_queue *mq, message_subscriber *sub)
+{
+ __isula_auto_prw_unlock pthread_rwlock_t *lock = NULL;
+ if (mq == NULL) {
+ ERROR("Invalid argument");
+ return;
+ }
+
+ if (pthread_rwlock_wrlock(&mq->rwlock) != 0) {
+ ERROR("Failed to lock rwlock");
+ return;
+ }
+ lock = &mq->rwlock;
+
+ if (map_remove(mq->subscribers, sub) == false) {
+ ERROR("Failed to remove subscriber");
+ return;
+ }
+
+ return;
+}
+
+int message_queue_publish(message_queue *mq, mailbox_message *msg)
+{
+ if (mq == NULL || msg == NULL) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+
+ if (blocking_queue_push(mq->messages, msg) != 0) {
+ ERROR("Failed to push message");
+ return -1;
+ }
+ return 0;
+}
+
+bool message_queue_have_subscribers(message_queue *mq)
+{
+ __isula_auto_prw_unlock pthread_rwlock_t *lock = NULL;
+ if (mq == NULL) {
+ ERROR("Invalid argument");
+ return false;
+ }
+
+ if (pthread_rwlock_wrlock(&mq->rwlock) != 0) {
+ ERROR("Failed to lock rwlock");
+ return false;
+ }
+ lock = &mq->rwlock;
+
+ return map_size(mq->subscribers) > 0;
+}
diff --git a/src/daemon/mailbox/message_queue.h b/src/daemon/mailbox/message_queue.h
new file mode 100644
index 00000000..7905840f
--- /dev/null
+++ b/src/daemon/mailbox/message_queue.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide message queue definition
+ ******************************************************************************/
+
+#ifndef DAEMON_MESSAGE_MESSAGE_QUEUE_H
+#define DAEMON_MESSAGE_MESSAGE_QUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pthread.h>
+
+#include "blocking_queue.h"
+#include "mailbox_message.h"
+#include "map.h"
+#include "message_subscriber.h"
+
+typedef struct message_queue {
+ blocking_queue *messages;
+
+ // lock for set of subscribers
+ pthread_rwlock_t rwlock;
+
+ map_t *subscribers;
+
+ int64_t sub_timeout;
+} message_queue;
+
+message_queue *message_queue_create(void (*release)(void *));
+
+void message_queue_shutdown(message_queue *mq);
+
+message_subscriber *message_queue_subscribe(message_queue *mq, void (*release)(void *));
+
+void message_queue_unsubscribe(message_queue *mq, message_subscriber *sub);
+
+int message_queue_publish(message_queue *mq, mailbox_message *msg);
+
+bool message_queue_have_subscribers(message_queue *mq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/daemon/mailbox/message_subscriber.c b/src/daemon/mailbox/message_subscriber.c
new file mode 100644
index 00000000..8ef3cb58
--- /dev/null
+++ b/src/daemon/mailbox/message_subscriber.c
@@ -0,0 +1,85 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide message subscriber definition
+ ******************************************************************************/
+
+#include "message_subscriber.h"
+
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+
+message_subscriber *message_subscriber_create(int64_t timeout, void (*release)(void *))
+{
+ message_subscriber *sub = (message_subscriber *)util_common_calloc_s(sizeof(message_subscriber));
+ if (sub == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+ sub->queue = blocking_queue_create(timeout, release);
+ if (sub->queue == NULL) {
+ ERROR("Failed to create blocking queue");
+ free(sub);
+ return NULL;
+ }
+ return sub;
+}
+
+int message_subscriber_push(message_subscriber *sub, mailbox_message *msg)
+{
+ if (sub == NULL || msg == NULL) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+
+ if (mailbox_message_ref(msg) != 0) {
+ ERROR("Failed to get message");
+ return -1;
+ }
+
+ if (blocking_queue_push(sub->queue, msg) != 0) {
+ ERROR("Failed to push message to queue");
+ mailbox_message_unref(msg);
+ return -1;
+ }
+
+ return 0;
+}
+
+int message_subscriber_pop(message_subscriber *sub, mailbox_message **msg)
+{
+ if (sub == NULL) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+ return blocking_queue_pop(sub->queue, (void **)msg);
+}
+
+void message_subscriber_shutdown(message_subscriber *sub)
+{
+ if (sub == NULL) {
+ return;
+ }
+
+ blocking_queue_clear(sub->queue);
+ (void)blocking_queue_push(sub->queue, NULL);
+}
+
+void message_subscriber_destroy(message_subscriber *sub)
+{
+ if (sub == NULL) {
+ return;
+ }
+ blocking_queue_destroy(sub->queue);
+ free(sub);
+}
diff --git a/src/daemon/mailbox/message_subscriber.h b/src/daemon/mailbox/message_subscriber.h
new file mode 100644
index 00000000..de4574d9
--- /dev/null
+++ b/src/daemon/mailbox/message_subscriber.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide message subscriber definition
+ ******************************************************************************/
+
+#ifndef SRC_DAEMON_MAILBOX_MESSAGE_SUBSCRIBER_H
+#define SRC_DAEMON_MAILBOX_MESSAGE_SUBSCRIBER_H
+
+#include "blocking_queue.h"
+#include "mailbox_message.h"
+
+typedef struct {
+ blocking_queue *queue;
+} message_subscriber;
+
+message_subscriber *message_subscriber_create(int64_t timeout, void (*release)(void *));
+
+void message_subscriber_shutdown(message_subscriber *sub);
+
+void message_subscriber_destroy(message_subscriber *sub);
+
+int message_subscriber_push(message_subscriber *sub, mailbox_message *msg);
+
+int message_subscriber_pop(message_subscriber *sub, mailbox_message **msg);
+
+// define auto free function callback for blocking queue
+define_auto_cleanup_callback(message_subscriber_destroy, message_subscriber);
+// define auto free macro for blocking queue
+#define __isula_auto_subscriber auto_cleanup_tag(message_subscriber_destroy)
+
+#endif
diff --git a/src/daemon/modules/api/container_api.h b/src/daemon/modules/api/container_api.h
index 830fd696..55c59980 100644
--- a/src/daemon/modules/api/container_api.h
+++ b/src/daemon/modules/api/container_api.h
@@ -289,6 +289,11 @@ static inline bool is_sandbox_container(container_sandbox_info *sandbox)
{
return sandbox != NULL && sandbox->is_sandbox_container;
}
+
+static inline bool is_container_in_sandbox(container_sandbox_info *sandbox)
+{
+ return sandbox != NULL && !sandbox->is_sandbox_container;
+}
#endif
#if defined(__cplusplus) || defined(c_plusplus)
diff --git a/src/daemon/modules/container/supervisor/supervisor.c b/src/daemon/modules/container/supervisor/supervisor.c
index 1b7da383..83d46268 100644
--- a/src/daemon/modules/container/supervisor/supervisor.c
+++ b/src/daemon/modules/container/supervisor/supervisor.c
@@ -38,6 +38,7 @@
#include "container_api.h"
#include "event_type.h"
#include "utils_file.h"
+#include "mailbox.h"
#ifdef ENABLE_CRI_API_V1
#include "sandbox_ops.h"
#endif
@@ -51,6 +52,7 @@ struct supervisor_handler_data {
int fd;
int exit_code;
char *name;
+ char *sandbox_name;
char *runtime;
bool is_sandbox_container;
pid_ppid_info_t pid_info;
@@ -152,6 +154,9 @@ static void supervisor_handler_data_free(struct supervisor_handler_data *data)
free(data->name);
data->name = NULL;
+ free(data->sandbox_name);
+ data->sandbox_name = NULL;
+
free(data->runtime);
data->runtime = NULL;
@@ -172,6 +177,9 @@ static void *clean_resources_thread(void *arg)
pid_t pid = data->pid_info.pid;
int retry_count = 0;
int max_retry = 10;
+#ifdef ENABLE_CRI_API_V1
+ cri_container_message_t msg;
+#endif
ret = pthread_detach(pthread_self());
if (ret != 0) {
@@ -218,6 +226,13 @@ retry:
(void)isulad_monitor_send_container_event(name, STOPPED, (int)pid, data->exit_code, NULL, NULL);
#ifdef ENABLE_CRI_API_V1
+ if (data->sandbox_name) {
+ msg.container_id = name;
+ msg.sandbox_id = data->sandbox_name;
+ msg.type = CRI_CONTAINER_MESSAGE_TYPE_STOPPED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &msg);
+ }
+
if (data->is_sandbox_container) {
if (sandbox_on_sandbox_exit(name, data->exit_code) < 0) {
ERROR("Failed to handle sandbox %s exit", name);
@@ -329,6 +344,9 @@ int container_supervisor_add_exit_monitor(int fd, const char *exit_fifo, const p
data->runtime = util_strdup_s(cont->runtime);
#ifdef ENABLE_CRI_API_V1
data->is_sandbox_container = is_sandbox_container(cont->common_config->sandbox_info);
+ if (is_container_in_sandbox(cont->common_config->sandbox_info)) {
+ data->sandbox_name = util_strdup_s(cont->common_config->sandbox_info->id);
+ }
#endif
data->pid_info.pid = pid_info->pid;
data->pid_info.start_time = pid_info->start_time;
diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc
index 7b6496ed..c70116c1 100644
--- a/src/daemon/sandbox/sandbox.cc
+++ b/src/daemon/sandbox/sandbox.cc
@@ -37,6 +37,7 @@
#include "cxxutils.h"
#include "controller_manager.h"
#include "utils_timestamp.h"
+#include "mailbox.h"
#define SANDBOX_READY_STATE_STR "SANDBOX_READY"
#define SANDBOX_NOTREADY_STATE_STR "SANDBOX_NOTREADY"
@@ -527,6 +528,14 @@ void Sandbox::OnSandboxExit(const ControllerExitInfo &exitInfo)
if (!SaveState(error)) {
ERROR("Failed to save sandbox state, %s", m_id.c_str());
}
+
+ if (error.Empty()) {
+ cri_container_message_t msg = { 0 };
+ msg.container_id = GetId().c_str();
+ msg.sandbox_id = GetId().c_str();
+ msg.type = CRI_CONTAINER_MESSAGE_TYPE_STOPPED;
+ mailbox_publish(MAILBOX_TOPIC_CRI_CONTAINER, &msg);
+ }
}
auto Sandbox::UpdateStatus(Errors &error) -> bool
diff --git a/src/utils/cutils/blocking_queue.c b/src/utils/cutils/blocking_queue.c
new file mode 100644
index 00000000..7c9c5f50
--- /dev/null
+++ b/src/utils/cutils/blocking_queue.c
@@ -0,0 +1,185 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide blocking queue definition
+ ******************************************************************************/
+
+#include "blocking_queue.h"
+
+#include <pthread.h>
+#include <time.h>
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+#include "utils_timestamp.h"
+
+// create blocking queue with timeout(ms), if timeout < 0, then with no timeout
+blocking_queue *blocking_queue_create(int64_t timeout, void (*release)(void *))
+{
+ __isula_auto_free blocking_queue *queue = NULL;
+ __isula_auto_free blocking_node *node = NULL;
+ queue = (blocking_queue *)util_common_calloc_s(sizeof(blocking_queue));
+ if (queue == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+ node = (blocking_node *)util_common_calloc_s(sizeof(blocking_node));
+ if (node == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ if (pthread_mutex_init(&queue->lock, NULL) != 0) {
+ ERROR("Failed to init mutex");
+ return NULL;
+ }
+
+ if (pthread_cond_init(&queue->not_empty, NULL) != 0) {
+ ERROR("Failed to init cond");
+ (void)pthread_mutex_destroy(&queue->lock);
+ return NULL;
+ }
+
+ queue->head = node;
+ queue->tail = node;
+ node = NULL;
+ queue->release = release;
+
+ if (timeout >= 0) {
+ queue->timeout.tv_sec = timeout / (Time_Second / Time_Milli);
+ queue->timeout.tv_nsec = (timeout % (Time_Second / Time_Milli) ) * Time_Milli;
+ } else {
+ queue->timeout.tv_sec = -1;
+ }
+
+ return isula_transfer_ptr(queue);
+}
+
+int blocking_queue_push(blocking_queue *queue, void *data)
+{
+ __isula_auto_free blocking_node *new_node = NULL;
+ __isula_auto_pm_unlock pthread_mutex_t *lock = NULL;
+ if (queue == NULL) {
+ ERROR("Invalid NULL arguments");
+ return -1;
+ }
+
+ new_node = (blocking_node *)util_common_calloc_s(sizeof(blocking_node));
+ if (new_node == NULL) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ new_node->data = data;
+ new_node->next = NULL;
+
+ if (pthread_mutex_lock(&queue->lock) != 0) {
+ ERROR("Failed to lock mutex");
+ return -1;
+ }
+ lock = &queue->lock;
+
+ queue->tail->next = new_node;
+ queue->tail = new_node;
+ new_node = NULL;
+
+ if (pthread_cond_broadcast(&queue->not_empty) != 0) {
+ ERROR("Failed to broadcast cond");
+ }
+
+ return 0;
+}
+
+int blocking_queue_pop(blocking_queue *queue, void **data) {
+ if (queue == NULL || data == NULL) {
+ ERROR("Invalid NULL arguments");
+ return -1;
+ }
+
+ __isula_auto_pm_unlock pthread_mutex_t *lock = NULL;
+ if (pthread_mutex_lock(&queue->lock) != 0) {
+ ERROR("Failed to lock mutex");
+ return -1;
+ }
+ lock = &queue->lock;
+
+ while (queue->head->next == NULL) {
+ if (queue->timeout.tv_sec >= 0) {
+ int ret = pthread_cond_timedwait(&queue->not_empty, &queue->lock, &queue->timeout);
+ if (ret != 0) {
+ if (ret != ETIMEDOUT) {
+ ERROR("Failed to wait cond");
+ }
+ return ret;
+ }
+ } else {
+ int ret = pthread_cond_wait(&queue->not_empty, &queue->lock);
+ if (ret != 0) {
+ ERROR("Failed to wait cond");
+ return ret;
+ }
+ }
+ }
+
+ blocking_node *old_head = queue->head;
+ blocking_node *new_head = old_head->next;
+ *data = new_head->data;
+ queue->head = new_head;
+
+ free(old_head);
+ return 0;
+}
+
+void blocking_queue_clear(blocking_queue *queue)
+{
+ if (queue == NULL) {
+ return;
+ }
+
+ __isula_auto_pm_unlock pthread_mutex_t *lock = NULL;
+ // clear all nodes in queue
+ if (queue == NULL) {
+ ERROR("Invalid NULL arguments");
+ return;
+ }
+
+ if (pthread_mutex_lock(&queue->lock) != 0) {
+ ERROR("Failed to lock mutex");
+ return;
+ }
+ lock = &queue->lock;
+
+ while (queue->head->next != NULL) {
+ blocking_node *old_head = queue->head;
+ blocking_node *new_head = old_head->next;
+ if (queue->release) {
+ queue->release(old_head->data);
+ }
+ free(old_head);
+ queue->head = new_head;
+ }
+}
+
+// ensure there is no other thread executing enqueue or dequeue operation
+void blocking_queue_destroy(blocking_queue *queue)
+{
+ if (queue == NULL) {
+ return;
+ }
+
+ blocking_queue_clear(queue);
+
+ (void)pthread_mutex_destroy(&queue->lock);
+
+ (void)pthread_cond_destroy(&queue->not_empty);
+
+ free(queue);
+}
diff --git a/src/utils/cutils/blocking_queue.h b/src/utils/cutils/blocking_queue.h
new file mode 100644
index 00000000..1c52a9d3
--- /dev/null
+++ b/src/utils/cutils/blocking_queue.h
@@ -0,0 +1,66 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-03-25
+ * Description: provide blocking queue definition
+ ******************************************************************************/
+
+#ifndef DAEMON_UTILS_CUTILS_BLOCKING_QUEUE_H
+#define DAEMON_UTILS_CUTILS_BLOCKING_QUEUE_H
+
+#include <pthread.h>
+#include <time.h>
+#include <isula_libutils/auto_cleanup.h>
+
+#include "utils_timestamp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLOCKING_QUEUE_NO_TIMEOUT -1
+
+typedef struct blocking_node {
+ void *data;
+ struct blocking_node *next;
+} blocking_node;
+
+typedef struct blocking_queue {
+ blocking_node *head;
+ blocking_node *tail;
+ pthread_mutex_t lock;
+ struct timespec timeout;
+ pthread_cond_t not_empty;
+ void (*release)(void *);
+} blocking_queue;
+
+// create blocking queue with timeout(ms), if timeout < 0, then with no timeout
+blocking_queue *blocking_queue_create(int64_t timeout, void (*release)(void *));
+
+int blocking_queue_push(blocking_queue *queue, void *data);
+
+int blocking_queue_pop(blocking_queue *queue, void **data);
+
+void blocking_queue_clear(blocking_queue *queue);
+
+// ensure there is no other thread executing enqueue or dequeue operation
+void blocking_queue_destroy(blocking_queue *queue);
+
+// define auto free function callback for blocking queue
+define_auto_cleanup_callback(blocking_queue_destroy, blocking_queue);
+// define auto free macro for blocking queue
+#define __isula_auto_blocking_queue auto_cleanup_tag(blocking_queue_destroy)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/test/mocks/mailbox_mock.cc b/test/mocks/mailbox_mock.cc
new file mode 100644
index 00000000..601b804e
--- /dev/null
+++ b/test/mocks/mailbox_mock.cc
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-04-02
+ * Description: mailbox mock
+ ******************************************************************************/
+
+#include "mailbox_mock.h"
+
+MockMailbox *g_mailbox_mock = nullptr;
+
+void Mailbox_SetMock(MockMailbox* mock)
+{
+ g_mailbox_mock = mock;
+}
+
+void mailbox_publish(mailbox_topic topic, void *data)
+{
+ if (g_mailbox_mock != nullptr) {
+ g_mailbox_mock->MailboxPublish(topic, data);
+ }
+}
diff --git a/test/mocks/mailbox_mock.h b/test/mocks/mailbox_mock.h
new file mode 100644
index 00000000..ce48f0fc
--- /dev/null
+++ b/test/mocks/mailbox_mock.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ * http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: jikai
+ * Create: 2024-04-02
+ * Description: mailbox mock
+ ******************************************************************************/
+
+#ifndef _ISULAD_TEST_MOCKS_MAILBOX_MOCK_H
+#define _ISULAD_TEST_MOCKS_MAILBOX_MOCK_H
+
+#include <gmock/gmock.h>
+#include "mailbox.h"
+
+class MockMailbox {
+public:
+ virtual ~MockMailbox() = default;
+ MOCK_METHOD2(MailboxPublish, void(mailbox_topic topic, void *data));
+};
+
+void Mailbox_SetMock(MockMailbox* mock);
+
+#endif
diff --git a/test/sandbox/controller/shim/CMakeLists.txt b/test/sandbox/controller/shim/CMakeLists.txt
index 6423bb80..26a66e51 100644
--- a/test/sandbox/controller/shim/CMakeLists.txt
+++ b/test/sandbox/controller/shim/CMakeLists.txt
@@ -7,6 +7,7 @@ add_executable(${EXE}
${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/v1/v1_cri_helpers.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/v1/v1_cri_security_context.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/v1/v1_naming.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/checkpoint_handler.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/cri_constants.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/cri/cri_helpers.cc
diff --git a/test/sandbox/sandbox/CMakeLists.txt b/test/sandbox/sandbox/CMakeLists.txt
index 138d4d8d..2a35388f 100644
--- a/test/sandbox/sandbox/CMakeLists.txt
+++ b/test/sandbox/sandbox/CMakeLists.txt
@@ -23,6 +23,7 @@ add_executable(${EXE}
${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/grpc_sandboxer_client_mock.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/controller_stub_mock.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/shim_controller_mock.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/mailbox_mock.cc
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/err_msg.c
${CMAKE_CURRENT_SOURCE_DIR}/sandbox_ut.cc)
@@ -33,6 +34,7 @@ target_include_directories(${EXE} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/entry/cri
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/executor
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/mailbox
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/shim
${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer
--
2.34.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yanyir/iSulad.git
git@gitee.com:yanyir/iSulad.git
yanyir
iSulad
iSulad
master

搜索帮助