1 Star 0 Fork 44

jchzhou/lxc

forked from src-openEuler/lxc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
0004-iSulad-adapt-confile-lxccontainer-and-start.patch 91.23 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310
From 3e7fb35a35cff34be2bb7ace0b239d540fe0657f Mon Sep 17 00:00:00 2001
From: zhangxiaoyu <[email protected]>
Date: Wed, 26 Jul 2023 14:57:33 +0800
Subject: [PATCH] [iSulad] adapt confile lxccontainer and start
Signed-off-by: zhangxiaoyu <[email protected]>
---
src/lxc/conf.c | 11 -
src/lxc/conf.h | 4 -
src/lxc/confile.c | 558 +++++++++++++++++++++++++
src/lxc/lxccontainer.c | 899 +++++++++++++++++++++++++++++++++++++++-
src/lxc/lxccontainer.h | 197 +++++++++
src/lxc/start.c | 902 +++++++++++++++++++++++++++++++++++++++++
src/lxc/start.h | 18 +
7 files changed, 2573 insertions(+), 16 deletions(-)
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index a0e0375..187e60e 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -5242,7 +5242,6 @@ void lxc_conf_free(struct lxc_conf *conf)
}
free(conf->systemd);
lxc_clear_init_args(conf);
- lxc_clear_init_groups(conf);
lxc_clear_populate_devices(conf);
lxc_clear_rootfs_masked_paths(conf);
lxc_clear_rootfs_ro_paths(conf);
@@ -7427,16 +7426,6 @@ int lxc_clear_init_args(struct lxc_conf *lxc_conf)
return 0;
}
-/*isulad clear init groups*/
-int lxc_clear_init_groups(struct lxc_conf *lxc_conf)
-{
- free(lxc_conf->init_groups);
- lxc_conf->init_groups = NULL;
- lxc_conf->init_groups_len = 0;
-
- return 0;
-}
-
/*isulad: clear populate devices*/
int lxc_clear_populate_devices(struct lxc_conf *c)
{
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 683b8ba..108e05b 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -622,9 +622,6 @@ struct lxc_conf {
char **init_argv;
size_t init_argc;
- gid_t *init_groups;
- size_t init_groups_len;
-
/* populate devices */
struct lxc_list populate_devs;
mode_t umask; // umask value
@@ -794,7 +791,6 @@ __hidden extern int parse_cap(const char *cap_name, __u32 *cap);
#ifdef HAVE_ISULAD
// isulad add
__hidden int lxc_clear_init_args(struct lxc_conf *lxc_conf);
-__hidden int lxc_clear_init_groups(struct lxc_conf *lxc_conf);
__hidden int lxc_clear_populate_devices(struct lxc_conf *c);
__hidden int lxc_clear_rootfs_masked_paths(struct lxc_conf *c);
__hidden int lxc_clear_rootfs_ro_paths(struct lxc_conf *c);
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 7966d32..1492776 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -157,6 +157,18 @@ lxc_config_define(uts_name);
lxc_config_define(sysctl);
lxc_config_define(proc);
lxc_config_define(sched_core);
+#ifdef HAVE_ISULAD
+lxc_config_define(init_args);
+lxc_config_define(populate_device);
+lxc_config_define(umask);
+lxc_config_define(rootfs_masked_paths);
+lxc_config_define(rootfs_ro_paths);
+lxc_config_define(systemd);
+lxc_config_define(console_log_driver);
+lxc_config_define(console_syslog_tag);
+lxc_config_define(console_syslog_facility);
+lxc_config_define(selinux_mount_context);
+#endif
static int set_config_unsupported_key(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
@@ -274,6 +286,18 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.uts.name", true, set_config_uts_name, get_config_uts_name, clr_config_uts_name, },
{ "lxc.sysctl", false, set_config_sysctl, get_config_sysctl, clr_config_sysctl, },
{ "lxc.proc", false, set_config_proc, get_config_proc, clr_config_proc, },
+#ifdef HAVE_ISULAD
+ { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, },
+ { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, },
+ { "lxc.isulad.umask", set_config_umask, get_config_umask, clr_config_umask, },
+ { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, },
+ { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, },
+ { "lxc.isulad.systemd", set_config_systemd, get_config_systemd, clr_config_systemd, },
+ { "lxc.console.logdriver", set_config_console_log_driver, get_config_console_log_driver, clr_config_console_log_driver, },
+ { "lxc.console.syslog_tag", set_config_console_syslog_tag, get_config_console_syslog_tag, clr_config_console_syslog_tag, },
+ { "lxc.console.syslog_facility", set_config_console_syslog_facility, get_config_console_syslog_facility, clr_config_console_syslog_facility, },
+ { "lxc.selinux.mount_context", set_config_selinux_mount_context, get_config_selinux_mount_context, clr_config_selinux_mount_context, },
+#endif
};
static struct lxc_config_t unsupported_config_key = {
@@ -1588,7 +1612,12 @@ static int set_config_environment(const char *key, const char *value,
if (!new_env)
return ret_errno(ENOMEM);
+#ifdef HAVE_ISULAD
+ /* isulad: recover space replaced by SPACE_MAGIC_STR */
+ dup = lxc_string_replace(SPACE_MAGIC_STR, " ", value);
+#else
dup = strdup(value);
+#endif
if (!dup)
return ret_errno(ENOMEM);
@@ -2558,8 +2587,11 @@ static int set_config_console_rotate(const char *key, const char *value,
if (ret)
return ret_errno(EINVAL);
+#ifndef HAVE_ISULAD
+ /* isulad: support rotate muti-files */
if (lxc_conf->console.log_rotate > 1)
return log_error_errno(-EINVAL, EINVAL, "The \"lxc.console.rotate\" config key can only be set to 0 or 1");
+#endif
return 0;
}
@@ -3049,6 +3081,54 @@ struct parse_line_conf {
bool from_include;
};
+#ifdef HAVE_ISULAD
+// escape_string_decode compress some escape characters
+static char *escape_string_decode(const char *src)
+{
+ size_t src_end = 0;
+ size_t dst_end = 0;
+ size_t len = 0;
+ char *dst = NULL;
+
+ if (src == NULL) {
+ return NULL;
+ }
+
+ len = strlen(src);
+ if (len == 0) {
+ return NULL;
+ }
+
+ dst = calloc(1, len + 1);
+ if (dst == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ while(src_end < len) {
+ if (src[src_end] == '\\') {
+ switch (src[++src_end])
+ {
+ case 'r': dst[dst_end] = '\r'; break;
+ case 'n': dst[dst_end] = '\n'; break;
+ case 'f': dst[dst_end] = '\f'; break;
+ case 'b': dst[dst_end] = '\b'; break;
+ case 't': dst[dst_end] = '\t'; break;
+ case '\\': dst[dst_end] = '\\'; break;
+ // default do not decode
+ default: dst[dst_end++] = '\\'; dst[dst_end] = src[src_end]; break;
+ }
+ } else {
+ dst[dst_end] = src[src_end];
+ }
+ dst_end++;
+ src_end++;
+ }
+
+ return dst;
+}
+#endif
+
static int parse_line(char *buffer, void *data)
{
__do_free char *linep = NULL;
@@ -3058,6 +3138,9 @@ static int parse_line(char *buffer, void *data)
int ret;
char *dup = buffer;
struct parse_line_conf *plc = data;
+#ifdef HAVE_ISULAD
+ __do_free char *value_decode = NULL;
+#endif
if (!plc->conf)
return syserror_set(-EINVAL, "Missing config");
@@ -3118,7 +3201,15 @@ static int parse_line(char *buffer, void *data)
}
config = lxc_get_config(key);
+#ifdef HAVE_ISULAD
+ value_decode = escape_string_decode(value);
+ if (value_decode == NULL) {
+ ERROR("Value %s decode failed", value);
+ }
+ ret = config->set(key, value_decode ? value_decode: value, plc->conf, NULL);
+#else
return config->set(key, value, plc->conf, NULL);
+#endif
}
static struct new_config_item *parse_new_conf_line(char *buffer)
@@ -3222,6 +3313,12 @@ bool lxc_config_define_load(struct lxc_list *defines, struct lxc_container *c)
lxc_list_for_each(it, defines) {
struct new_config_item *new_item = it->elem;
+#ifdef HAVE_ISULAD
+ if (strcmp(new_item->key, LXC_IMAGE_OCI_KEY) == 0) {
+ c->set_oci_type(c, true);
+ continue;
+ }
+#endif
bret = c->set_config_item(c, new_item->key, new_item->val);
if (!bret)
break;
@@ -6764,3 +6861,464 @@ static int clr_config_sched_core(const char *key, struct lxc_conf *c, void *data
c->sched_core = false;
return 0;
}
+
+
+#ifdef HAVE_ISULAD
+/* isulad: set config for init args */
+static int set_config_init_args(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret = 0;
+ char **tmp = NULL;
+ char *new_value = NULL;
+
+ ret = set_config_string_item(&new_value, value);
+ if (ret || !new_value)
+ return ret;
+
+ tmp = (char **)realloc(lxc_conf->init_argv, (lxc_conf->init_argc + 1) * sizeof(char *));
+ if (!tmp) {
+ ERROR("Out of memory");
+ free(new_value);
+ return -1;
+ }
+
+ lxc_conf->init_argv = tmp;
+
+ lxc_conf->init_argv[lxc_conf->init_argc] = new_value;
+ lxc_conf->init_argc++;
+
+ return 0;
+}
+
+/* isulad: get config init args */
+static int get_config_init_args(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int i, len, fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ for (i = 0; i < c->init_argc; i++) {
+ strprint(retv, inlen, "%s", c->init_argv[i]);
+ }
+
+ return fulllen;
+}
+
+/* isulad: clr config init args*/
+static inline int clr_config_init_args(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ return lxc_clear_init_args(c);
+}
+
+/* isulad: set config for populate device */
+static int set_config_populate_device(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int ret = 0, major = 0, minor = 0;
+ uid_t uid = (uid_t)-1;
+ gid_t gid = (gid_t)-1;
+ char name[4096] = {0}; /* MAX dev path name */
+ char type[3] = {0};
+ char *replace_value = NULL;
+ mode_t filemode = 0;
+ struct lxc_list *iter = NULL;
+ struct lxc_list *dev_list = NULL;
+ struct lxc_populate_devs *dev_elem = NULL;
+
+ if (lxc_config_value_empty(value))
+ return lxc_clear_populate_devices(lxc_conf);
+
+ /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID
+ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
+ */
+ ret = sscanf(value, "%4095[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid);
+ if (ret != 7)
+ return -1;
+
+ /* find existing list element */
+ lxc_list_for_each(iter, &lxc_conf->populate_devs) {
+ dev_elem = iter->elem;
+
+ if (strcmp(name, dev_elem->name) != 0)
+ continue;
+
+ replace_value = safe_strdup(type);
+
+ free(dev_elem->type);
+ dev_elem->type = replace_value;
+ dev_elem->file_mode = filemode;
+ dev_elem->maj = major;
+ dev_elem->min = minor;
+ dev_elem->uid = (uid_t)uid;
+ dev_elem->gid = (gid_t)gid;
+ return 0;
+ }
+
+ /* allocate list element */
+ dev_list = malloc(sizeof(*dev_list));
+ if (dev_list == NULL)
+ goto on_error;
+
+ lxc_list_init(dev_list);
+
+ dev_elem = malloc(sizeof(*dev_elem));
+ if (dev_elem == NULL)
+ goto on_error;
+ memset(dev_elem, 0, sizeof(*dev_elem));
+
+ dev_elem->name = safe_strdup(name);
+
+ dev_elem->type = safe_strdup(type);
+
+ dev_elem->file_mode = filemode;
+ dev_elem->maj = major;
+ dev_elem->min = minor;
+ dev_elem->uid = (uid_t)uid;
+ dev_elem->gid = (gid_t)gid;
+
+ lxc_list_add_elem(dev_list, dev_elem);
+
+ lxc_list_add_tail(&lxc_conf->populate_devs, dev_list);
+
+ return 0;
+
+on_error:
+ free(dev_list);
+ if (dev_elem) {
+ free(dev_elem->name);
+ free(dev_elem->type);
+ free(dev_elem);
+ }
+ return -1;
+}
+
+/* isulad: get config populate device
+ * If you ask for 'lxc.populate.device', then all populate device
+ * entries will be printed, in 'lxc.populate.device = path_in_container:type:major:minor:mode:uid:gid' format.
+ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
+ */
+static int get_config_populate_device(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len;
+ struct lxc_list *it = NULL;
+ int fulllen = 0;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ lxc_list_for_each(it, &c->populate_devs) {
+ struct lxc_populate_devs *elem = it->elem;
+ strprint(retv, inlen, "lxc.populate.device = %s:%s:%d:%d:%o:%u:%u\n",
+ elem->name, elem->type, elem->maj,
+ elem->min, elem->file_mode, elem->uid, elem->gid);
+ }
+
+ return fulllen;
+}
+
+/* isulad: clr config populate devices*/
+static inline int clr_config_populate_device(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ return lxc_clear_populate_devices(c);
+}
+
+/* isulad: set config for umask */
+static int set_config_umask(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value)) {
+ ERROR("Empty umask");
+ return -1;
+ }
+
+ if (strcmp(value, "normal") == 0) {
+ lxc_conf->umask = 0022;
+ return 0;
+ } else if (strcmp(value, "secure") == 0) {
+ lxc_conf->umask = 0027;
+ return 0;
+ } else {
+ ERROR("Invalid native umask: %s", value);
+ return -1;
+ }
+}
+
+/* isulad add: get umask value*/
+static int get_config_umask(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_size_t(c, retv, inlen, c->umask);
+}
+
+/* isulad add: clear umask value */
+static inline int clr_config_umask(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ c->umask = 0027;
+ return 0;
+}
+
+/* isulad: set config for rootfs masked paths */
+static int set_config_rootfs_masked_paths(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ struct lxc_list *list_item = NULL;
+
+ if (lxc_config_value_empty(value))
+ return lxc_clear_rootfs_masked_paths(lxc_conf);
+
+ list_item = malloc(sizeof(*list_item));
+ if (list_item == NULL)
+ goto on_error;
+
+ list_item->elem = safe_strdup(value);
+
+ lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item);
+
+ return 0;
+
+on_error:
+ free(list_item);
+
+ return -1;
+}
+
+// isulad: get config rootfs masked paths
+static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len, fulllen = 0;
+ struct lxc_list *it = NULL;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ lxc_list_for_each(it, &c->rootfs.maskedpaths) {
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
+ }
+
+ return fulllen;
+}
+
+/* isulad: set config for rootfs ro paths */
+static int set_config_rootfs_ro_paths(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ struct lxc_list *list_item = NULL;
+
+ if (lxc_config_value_empty(value))
+ return lxc_clear_rootfs_ro_paths(lxc_conf);
+
+ list_item = malloc(sizeof(*list_item));
+ if (list_item == NULL)
+ goto on_error;
+
+ list_item->elem = safe_strdup(value);
+
+ lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item);
+
+ return 0;
+
+on_error:
+ free(list_item);
+
+ return -1;
+}
+
+// isulad: get config rootfs ro paths
+static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ int len, fulllen = 0;
+ struct lxc_list *it = NULL;
+
+ if (!retv)
+ inlen = 0;
+ else
+ memset(retv, 0, inlen);
+
+ lxc_list_for_each(it, &c->rootfs.ropaths) {
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
+ }
+
+ return fulllen;
+}
+
+/* isulad: clr config rootfs masked paths */
+static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ return lxc_clear_rootfs_masked_paths(c);
+}
+
+/* isulad: clr config rootfs ro paths */
+static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ return lxc_clear_rootfs_ro_paths(c);
+}
+
+/* isulad: set config for systemd */
+static int set_config_systemd(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (lxc_config_value_empty(value)) {
+ ERROR("Empty umask");
+ return -1;
+ }
+ lxc_conf->systemd = strdup(value);
+ return 0;
+}
+
+/* isulad add: get systemd value*/
+static int get_config_systemd(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_str(retv, inlen, c->systemd);
+}
+
+/* isulad add: clear systemd value */
+static inline int clr_config_systemd(const char *key, struct lxc_conf *c,
+ void *data)
+{
+ free(c->systemd);
+ c->systemd = NULL;
+ return 0;
+}
+
+static int set_config_console_log_driver(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ return set_config_string_item(&lxc_conf->console.log_driver, value);
+}
+
+static int set_config_console_syslog_tag(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (value == NULL) {
+ return -1;
+ }
+ return set_config_string_item(&lxc_conf->console.log_syslog_tag, value);
+}
+
+static int parse_facility(const char *facility)
+{
+#define FACILITIES_LEN 20
+ const char *facility_keys[FACILITIES_LEN] = {
+ "kern", "user", "mail", "daemon", "auth",
+ "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp",
+ "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"
+ };
+ const int facilities[FACILITIES_LEN] = {
+ LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_SYSLOG,
+ LOG_LPR, LOG_NEWS, LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_FTP,
+ LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4,
+ LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7
+ };
+ int i = 0;
+
+ if (facility == NULL) {
+ return -1;
+ }
+
+ for (; i < FACILITIES_LEN; i++) {
+ if (strcmp(facility, facility_keys[i]) == 0) {
+ return facilities[i];
+ }
+ }
+
+ return -1;
+}
+
+static int set_config_console_syslog_facility(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ int facility;
+
+ facility = parse_facility(value);
+ if (facility < 0) {
+ NOTICE("Invalid facility: %s", value);
+ facility = LOG_DAEMON;
+ }
+
+ lxc_conf->console.log_syslog_facility = facility;
+ return 0;
+}
+
+static int set_config_selinux_mount_context(const char *key, const char *value,
+ struct lxc_conf *lxc_conf, void *data)
+{
+ if (value != NULL && strcmp(value, "unconfined_t") == 0) {
+ return set_config_string_item(&lxc_conf->lsm_se_mount_context, NULL);
+ }
+
+ return set_config_string_item(&lxc_conf->lsm_se_mount_context, value);
+}
+
+static int get_config_console_log_driver(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_str(retv, inlen, c->console.log_driver);
+}
+
+static int get_config_console_syslog_tag(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_str(retv, inlen, c->console.log_syslog_tag);
+}
+
+static int get_config_console_syslog_facility(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_int(c, retv, inlen, c->console.log_syslog_facility);
+}
+
+static int get_config_selinux_mount_context(const char *key, char *retv, int inlen,
+ struct lxc_conf *c, void *data)
+{
+ return lxc_get_conf_str(retv, inlen, c->lsm_se_mount_context);
+}
+
+static inline int clr_config_console_log_driver(const char *key,
+ struct lxc_conf *c, void *data)
+{
+ free(c->console.log_driver);
+ c->console.log_driver = NULL;
+ return 0;
+}
+
+static inline int clr_config_console_syslog_tag(const char *key,
+ struct lxc_conf *c, void *data)
+{
+ free(c->console.log_syslog_tag);
+ c->console.log_syslog_tag= NULL;
+ return 0;
+}
+
+static inline int clr_config_console_syslog_facility(const char *key,
+ struct lxc_conf *c, void *data)
+{
+ c->console.log_syslog_facility = LOG_DAEMON;
+ return 0;
+}
+
+static inline int clr_config_selinux_mount_context(const char *key,
+ struct lxc_conf *c, void *data)
+{
+ free(c->lsm_se_mount_context);
+ c->lsm_se_mount_context = NULL;
+ return 0;
+}
+#endif
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 8df6059..d4495f7 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -62,6 +62,10 @@
#include "utils.h"
#include "version.h"
+#ifdef HAVE_ISULAD
+#include "exec_commands.h"
+#endif
+
#if HAVE_OPENSSL
#include <openssl/evp.h>
#endif
@@ -83,6 +87,11 @@
lxc_log_define(lxccontainer, lxc);
+#ifdef HAVE_ISULAD
+typedef bool (*func_is_io_stat_read)(const char *value);
+typedef bool (*func_is_io_stat_write)(const char *value);
+#endif
+
static bool do_lxcapi_destroy(struct lxc_container *c);
static const char *lxcapi_get_config_path(struct lxc_container *c);
#define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c)
@@ -272,6 +281,13 @@ static void lxc_container_free(struct lxc_container *c)
free(c->config_path);
c->config_path = NULL;
+#ifdef HAVE_ISULAD
+ free(c->exit_fifo);
+ c->exit_fifo = NULL;
+ free(c->ocihookfile);
+ c->ocihookfile = NULL;
+#endif
+
free(c);
}
@@ -652,6 +668,66 @@ static bool load_config_locked(struct lxc_container *c, const char *fname)
return true;
}
+#ifdef HAVE_ISULAD
+static bool load_ocihooks_locked(struct lxc_container *c)
+{
+ parser_error err = NULL;
+ oci_runtime_spec_hooks *hooks = NULL;
+
+ if (!c->lxc_conf)
+ c->lxc_conf = lxc_conf_init();
+
+ if (!c->lxc_conf)
+ return false;
+
+ hooks = oci_runtime_spec_hooks_parse_file(c->ocihookfile, NULL, &err);
+ if (!hooks) {
+ fprintf(stderr, "parse oci hooks config failed: %s\n", err);
+ free(err);
+ return true;
+ }
+ c->lxc_conf->ocihooks = hooks;
+
+ if (err)
+ free(err);
+ return true;
+}
+
+/*
+ * isulad: set oci hook file path
+ * */
+static bool set_oci_hook_config_filename(struct lxc_container *c)
+{
+#define OCI_HOOK_JSON_FILE_NAME "ocihooks.json"
+ char *newpath = NULL;
+ int len, ret;
+
+ if (!c->config_path)
+ return false;
+
+ /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */
+ if (strlen(c->config_path) + strlen(c->name) > SIZE_MAX - strlen(OCI_HOOK_JSON_FILE_NAME) - 3)
+ return false;
+ len = strlen(c->config_path) + strlen(c->name) + strlen(OCI_HOOK_JSON_FILE_NAME) + 3;
+
+ newpath = malloc(len);
+ if (newpath == NULL)
+ return false;
+
+ ret = snprintf(newpath, len, "%s/%s/%s", c->config_path, c->name, OCI_HOOK_JSON_FILE_NAME);
+ if (ret < 0 || ret >= len) {
+ fprintf(stderr, "Error printing out config file name\n");
+ free(newpath);
+ return false;
+ }
+
+ free(c->ocihookfile);
+ c->ocihookfile = newpath;
+
+ return true;
+}
+#endif
+
static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
{
int lret;
@@ -685,6 +761,11 @@ static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
ret = load_config_locked(c, fname);
+#ifdef HAVE_ISULAD
+ if (ret && file_exists(c->ocihookfile))
+ ret = load_ocihooks_locked(c);
+#endif
+
if (need_disklock)
container_disk_unlock(c);
else
@@ -884,6 +965,33 @@ static bool wait_on_daemonized_start(struct lxc_handler *handler, int pid)
return true;
}
+#ifdef HAVE_ISULAD
+/* isulad: use init argv as init cmd */
+static char **use_init_args(char **init_argv, size_t init_args)
+{
+ size_t i;
+ int nargs = 0;
+ char **argv;
+
+ if (!init_argv)
+ return NULL;
+
+ do {
+ argv = malloc(sizeof(char *));
+ } while (!argv);
+
+ argv[0] = NULL;
+ for (i = 0; i < init_args; i++)
+ push_arg(&argv, init_argv[i], &nargs);
+
+ if (nargs == 0) {
+ free(argv);
+ return NULL;
+ }
+ return argv;
+}
+#endif
+
static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
{
int ret;
@@ -894,6 +1002,11 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
NULL,
};
char **init_cmd = NULL;
+#ifdef HAVE_ISULAD
+ int keepfds[] = {-1, -1, -1, -1, -1};
+ ssize_t size_read;
+ char errbuf[BUFSIZ + 1] = {0};
+#endif
/* container does exist */
if (!c)
@@ -940,6 +1053,30 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
argv = init_cmd = split_init_cmd(conf->init_cmd);
}
+#ifdef HAVE_ISULAD
+ if (!argv) {
+ argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc);
+ }
+
+ // do not allow using default rootfs path when isulad
+ if (conf->rootfs.mount == NULL) {
+ ERROR("Empty rootfs path detected");
+ lxc_put_handler(handler);
+ return false;
+ }
+
+ // do not allow using default args when isulad
+ if (!argv) {
+ ERROR("Empty args detected");
+ lxc_put_handler(handler);
+ return false;
+ }
+
+ if (c->image_type_oci) {
+ handler->image_type_oci = true;
+ }
+#endif
+
/* ... otherwise use default_args. */
if (!argv) {
if (useinit) {
@@ -959,10 +1096,23 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
char title[2048];
pid_t pid_first, pid_second;
+#ifdef HAVE_ISULAD
+ //isulad: pipdfd for get error message of child or grandchild process.
+ if (pipe2(conf->errpipe, O_CLOEXEC) != 0) {
+ SYSERROR("Failed to init errpipe");
+ free_init_cmd(init_cmd);
+ lxc_put_handler(handler);
+ return false;
+ }
+#endif
+
pid_first = fork();
if (pid_first < 0) {
free_init_cmd(init_cmd);
lxc_put_handler(handler);
+#ifdef HAVE_ISULAD
+ lxc_close_error_pipe(conf->errpipe);
+#endif
return false;
}
@@ -972,11 +1122,25 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
* the PID file, child will do the free and unlink.
*/
c->pidfile = NULL;
+#ifdef HAVE_ISULAD
+ close(conf->errpipe[1]);
+ conf->errpipe[1] = -1;
+#endif
/* Wait for container to tell us whether it started
* successfully.
*/
started = wait_on_daemonized_start(handler, pid_first);
+#ifdef HAVE_ISULAD
+ if (!started) {
+ size_read = read(conf->errpipe[0], errbuf, BUFSIZ);
+ if (size_read > 0) {
+ conf->errmsg = safe_strdup(errbuf);
+ }
+ }
+ close(conf->errpipe[0]);
+ conf->errpipe[0] = -1;
+#endif
free_init_cmd(init_cmd);
lxc_put_handler(handler);
@@ -1012,6 +1176,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
if (pid_second != 0) {
free_init_cmd(init_cmd);
lxc_put_handler(handler);
+#ifdef HAVE_ISULAD
+ lxc_close_error_pipe(conf->errpipe);
+#endif
_exit(EXIT_SUCCESS);
}
@@ -1024,7 +1191,18 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
_exit(EXIT_FAILURE);
}
+#ifdef HAVE_ISULAD
+ keepfds[0] = handler->conf->maincmd_fd;
+ keepfds[1] = handler->state_socket_pair[0];
+ keepfds[2] = handler->state_socket_pair[1];
+ keepfds[4] = conf->errpipe[1];
+ close(conf->errpipe[0]);
+ conf->errpipe[0] = -1;
+ ret = lxc_check_inherited(conf, true, keepfds,
+ sizeof(keepfds) / sizeof(keepfds[0]));
+#else
ret = inherit_fds(handler, true);
+#endif
if (ret < 0)
_exit(EXIT_FAILURE);
@@ -1057,6 +1235,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
if (w < 0) {
free_init_cmd(init_cmd);
lxc_put_handler(handler);
+#ifdef HAVE_ISULAD
+ lxc_close_error_pipe(conf->errpipe);
+#endif
SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
@@ -1070,6 +1251,9 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
if (ret < 0) {
free_init_cmd(init_cmd);
lxc_put_handler(handler);
+#ifdef HAVE_ISULAD
+ lxc_close_error_pipe(conf->errpipe);
+#endif
SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
@@ -1080,6 +1264,19 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
}
}
+#ifdef HAVE_ISULAD
+ /* isulad: open exit fifo */
+ if (c->exit_fifo) {
+ conf->exit_fd = lxc_open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0);
+ if (conf->exit_fd < 0) {
+ ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno));
+ lxc_put_handler(handler);
+ ret = 1;
+ goto on_error;
+ }
+ }
+#endif
+
conf->reboot = REBOOT_NONE;
/* Unshare the mount namespace if requested */
@@ -1111,19 +1308,53 @@ reboot:
}
}
+#ifdef HAVE_ISULAD
+ keepfds[0] = handler->conf->maincmd_fd;
+ keepfds[1] = handler->state_socket_pair[0];
+ keepfds[2] = handler->state_socket_pair[1];
+
+ /* keep exit fifo fd */
+ if (conf->exit_fd >= 0) {
+ keepfds[3] = conf->exit_fd;
+ }
+ /* isulad: keep errpipe fd */
+ if (c->daemonize)
+ keepfds[4] = conf->errpipe[1];
+
+ ret = lxc_check_inherited(conf, c->daemonize, keepfds,
+ sizeof(keepfds) / sizeof(keepfds[0]));
+ if (ret < 0) {
+ lxc_put_handler(handler);
+ ret = 1;
+ goto on_error;
+ }
+#else
ret = inherit_fds(handler, c->daemonize);
if (ret < 0) {
lxc_put_handler(handler);
ret = 1;
goto on_error;
}
+#endif
+#ifndef HAVE_ISULAD
if (useinit)
ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
c->daemonize, &c->error_num);
else
ret = lxc_start(argv, handler, c->config_path, c->daemonize,
&c->error_num);
+#else
+ if (useinit) {
+ ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
+ c->daemonize, &c->error_num, c->start_timeout);
+ } else {
+ handler->disable_pty = c->disable_pty;
+ handler->open_stdin = c->open_stdin;
+ ret = lxc_start(argv, handler, c->config_path, c->daemonize,
+ &c->error_num, c->start_timeout);
+ }
+#endif
if (conf->reboot == REBOOT_REQ) {
INFO("Container requested reboot");
@@ -2065,7 +2296,12 @@ WRAP_API_1(bool, lxcapi_reboot2, int)
static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
{
__do_close int pidfd = -EBADF, state_client_fd = -EBADF;
+#ifdef HAVE_ISULAD
+ // isulad: keep default signal the same as docker
+ int haltsignal = SIGTERM;
+#else
int haltsignal = SIGPWR;
+#endif
pid_t pid = -1;
lxc_state_t states[MAX_STATE] = {0};
int killret, ret;
@@ -2084,9 +2320,10 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
/* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
if (c->lxc_conf && c->lxc_conf->haltsignal)
haltsignal = c->lxc_conf->haltsignal;
+#ifndef HAVE_ISULAD
else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
haltsignal = (SIGRTMIN + 3);
-
+#endif
/*
* Add a new state client before sending the shutdown signal so
@@ -2939,6 +3176,21 @@ static int lxc_unlink_exec_wrapper(void *data)
return unlink(arg);
}
+#ifdef HAVE_ISULAD
+static void container_sock_dir_delete(const char *name)
+{
+ __do_free char *sock_dir = NULL;
+
+ sock_dir = generate_named_unix_sock_dir(name);
+ if (sock_dir == NULL) {
+ ERROR("Failed to generate exec unix sock dir");
+ return;
+ }
+
+ (void)lxc_rmdir_onedev(sock_dir, NULL);
+}
+#endif
+
static bool container_destroy(struct lxc_container *c,
struct lxc_storage *storage)
{
@@ -2949,8 +3201,19 @@ static bool container_destroy(struct lxc_container *c,
bool bret = false;
int ret = 0;
+#ifdef HAVE_ISULAD
+ if (!c)
+ return false;
+ // isulad: if container is not defined, we need to remove disk lock file
+ // which is created in lxc_container_new.
+ if (!do_lxcapi_is_defined(c)) {
+ container_disk_removelock(c);
+ return false;
+ }
+#else
if (!c || !do_lxcapi_is_defined(c))
return false;
+#endif
conf = c->lxc_conf;
if (container_disk_lock(c))
@@ -3070,8 +3333,20 @@ static bool container_destroy(struct lxc_container *c,
if (ret < 0) {
ERROR("Failed to destroy directory \"%s\" for \"%s\"", path,
c->name);
+#ifdef HAVE_ISULAD
+ char msg[BUFSIZ] = { 0 };
+ ret = snprintf(msg, BUFSIZ, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error");
+ if (ret < 0 || ret >= BUFSIZ) {
+ ERROR("Sprintf failed");
+ goto out;
+ }
+ c->error_string = safe_strdup(msg);
+#endif
goto out;
}
+#ifdef HAVE_ISULAD
+ container_sock_dir_delete(c->name);
+#endif
INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
on_success:
@@ -3082,6 +3357,11 @@ out:
free(path);
container_disk_unlock(c);
+#ifdef HAVE_ISULAD
+ if (bret && container_disk_removelock(c)) {
+ bret = false;
+ }
+#endif
return bret;
}
@@ -4042,8 +4322,13 @@ static int lxcapi_attach(struct lxc_container *c,
current_config = c->lxc_conf;
+#ifdef HAVE_ISULAD
+ ret = lxc_attach(c, exec_function, exec_payload, options,
+ attached_process, &c->lxc_conf->errmsg);
+#else
ret = lxc_attach(c, exec_function, exec_payload, options,
attached_process);
+#endif
current_config = NULL;
return ret;
}
@@ -4063,7 +4348,11 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c,
command.program = (char *)program;
command.argv = (char **)argv;
+#ifdef HAVE_ISULAD
+ ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid, NULL);
+#else
ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid);
+#endif
if (ret < 0)
return ret;
@@ -5257,6 +5546,560 @@ static int do_lxcapi_seccomp_notify_fd_active(struct lxc_container *c)
WRAP_API(int, lxcapi_seccomp_notify_fd_active)
+#ifdef HAVE_ISULAD
+/* isulad add set console fifos*/
+static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out, const char *err)
+{
+ struct lxc_conf *conf = NULL;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ conf = c->lxc_conf;
+ if (in) {
+ if (conf->console.init_fifo[0])
+ free(conf->console.init_fifo[0]);
+ conf->console.init_fifo[0] = safe_strdup(in);
+ }
+ if (out) {
+ if (conf->console.init_fifo[1])
+ free(conf->console.init_fifo[1]);
+ conf->console.init_fifo[1] = safe_strdup(out);
+ }
+ if (err) {
+ if (conf->console.init_fifo[2])
+ free(conf->console.init_fifo[2]);
+ conf->console.init_fifo[2] = safe_strdup(err);
+ }
+
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_3(bool, lxcapi_set_terminal_default_fifos, const char *, const char *, const char *)
+
+/* isulad add set info file path */
+static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file)
+{
+ struct lxc_conf *conf = NULL;
+
+ if (!c || !c->lxc_conf || !info_file)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ conf = c->lxc_conf;
+ if (conf->container_info_file)
+ free(conf->container_info_file);
+ conf->container_info_file = safe_strdup(info_file);
+
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_container_info_file, const char *)
+
+static bool do_lxcapi_want_disable_pty(struct lxc_container *c, bool state)
+{
+ if (!c || !c->lxc_conf)
+ return false;
+
+ if (container_mem_lock(c))
+ return false;
+
+ c->disable_pty = state;
+
+ container_mem_unlock(c);
+
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_want_disable_pty, bool)
+
+static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state)
+{
+ if (!c || !c->lxc_conf)
+ return false;
+
+ if (container_mem_lock(c))
+ return false;
+
+ c->open_stdin = state;
+
+ container_mem_unlock(c);
+
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_want_open_stdin, bool)
+
+/* isulad add clean resources */
+static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo)
+{
+ bool ret = true;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo, err_fifo)) {
+ ERROR("Error set console fifos");
+ ret = false;
+ }
+
+ container_mem_unlock(c);
+ return ret;
+}
+
+WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *)
+
+static bool do_lxcapi_set_terminal_winch(struct lxc_container *c, unsigned int height, unsigned int width)
+{
+ bool ret = true;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ if (lxc_cmd_set_terminal_winch(c->name, c->config_path, height, width)) {
+ ERROR("Error set terminal winch");
+ ret = false;
+ }
+
+ container_mem_unlock(c);
+ return ret;
+}
+
+WRAP_API_2(bool, lxcapi_set_terminal_winch, unsigned int, unsigned int)
+
+static bool do_lxcapi_set_exec_terminal_winch(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width)
+{
+ bool ret = true;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ if (lxc_exec_cmd_set_terminal_winch(c->name, c->config_path, suffix, height, width)) {
+ ERROR("Error set terminal winch");
+ ret = false;
+ }
+
+ container_mem_unlock(c);
+ return ret;
+}
+
+WRAP_API_3(bool, lxcapi_set_exec_terminal_winch, const char *, unsigned int, unsigned int)
+
+/* isulad add clean resources */
+static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pid)
+{
+ int ret;
+
+ if (!c)
+ return false;
+
+ ret = do_lxcapi_clean_resource(c->name, c->config_path, c->lxc_conf, pid);
+ if (ret)
+ ERROR("Failed to clean container %s resource", c->name);
+ return ret == 0;
+
+}
+
+WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t)
+
+/* isulad get coantainer pids */
+static bool do_lxcapi_get_container_pids(struct lxc_container *c, pid_t **pids,size_t *pids_len)
+{
+ int ret;
+
+ if (!c)
+ return false;
+
+ ret = do_lxcapi_get_pids(c->name, c->config_path, c->lxc_conf, pids,pids_len);
+ if (ret)
+ ERROR("Failed to get container %s pids", c->name);
+ return ret == 0;
+
+}
+
+WRAP_API_2(bool, lxcapi_get_container_pids, pid_t **,size_t *)
+
+/* isulad add start timeout */
+static bool do_lxcapi_set_start_timeout(struct lxc_container *c, unsigned int start_timeout)
+{
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+ c->start_timeout = start_timeout;
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int)
+
+/* isulad add set image type */
+static bool do_lxcapi_set_oci_type(struct lxc_container *c, bool image_type_oci)
+{
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+ c->image_type_oci = image_type_oci;
+ container_mem_unlock(c);
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_set_oci_type, bool)
+
+static uint64_t metrics_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
+{
+ char buf[81] = {0};
+ int len = 0;
+ uint64_t val = 0;
+
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
+ if (len <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ return 0;
+ }
+
+ val = strtoull(buf, NULL, 0);
+ return val;
+}
+
+static uint64_t metrics_get_ull_with_max(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
+{
+ char buf[81] = {0};
+ int len = 0;
+ uint64_t val = 0;
+
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
+ if (len <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ return 0;
+ }
+
+ if (strcmp(buf, "max") == 0) {
+ return ULONG_MAX;
+ }
+
+ val = strtoull(buf, NULL, 0);
+ return val;
+}
+
+static inline bool is_blk_metrics_read(const char *value)
+{
+ return strcmp(value, "Read") == 0;
+}
+
+static inline bool is_blk_metrics_write(const char *value)
+{
+ return strcmp(value, "Write") == 0;
+}
+
+static inline bool is_blk_metrics_total(const char *value)
+{
+ return strcmp(value, "Total") == 0;
+}
+
+static void metrics_get_blk_stats(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats)
+{
+ char *buf = NULL;
+ int i = 0;
+ int len = 0;
+ int ret = 0;
+ char **lines = NULL;
+ char **cols = NULL;
+
+ len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
+ if (len <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ return;
+ }
+
+ buf = malloc(len + 1);
+ (void)memset(buf, 0, len + 1);
+ ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
+ if (ret <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ goto out;
+ }
+
+ lines = lxc_string_split_and_trim(buf, '\n');
+ if (lines == NULL) {
+ goto out;
+ }
+
+ (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
+
+ for (i = 0; lines[i]; i++) {
+ cols = lxc_string_split_and_trim(lines[i], ' ');
+ if (cols == NULL) {
+ goto err_out;
+ }
+ if (lxc_array_len((void **)cols) == 3) {
+ if (is_blk_metrics_read(cols[1])) {
+ stats->read += strtoull(cols[2], NULL, 0);
+ } else if (is_blk_metrics_write(cols[1])) {
+ stats->write += strtoull(cols[2], NULL, 0);
+ }
+ }
+ if (lxc_array_len((void **)cols) == 2 && is_blk_metrics_total(cols[0])) {
+ stats->total = strtoull(cols[1], NULL, 0);
+ }
+
+ lxc_free_array((void **)cols, free);
+ }
+err_out:
+ lxc_free_array((void **)lines, free);
+out:
+ free(buf);
+ return;
+}
+
+static void metrics_get_io_stats_v2(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats, func_is_io_stat_read is_io_stat_read, func_is_io_stat_write is_io_stat_write)
+{
+ char *buf = NULL;
+ int i = 0;
+ int j = 0;
+ int len = 0;
+ int ret = 0;
+ char **lines = NULL;
+ char **cols = NULL;
+ char **kv = NULL;
+
+ len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
+ if (len <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ return;
+ }
+
+ buf = malloc(len + 1);
+ (void)memset(buf, 0, len + 1);
+ ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
+ if (ret <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ goto out;
+ }
+
+ lines = lxc_string_split_and_trim(buf, '\n');
+ if (lines == NULL) {
+ goto out;
+ }
+
+ (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
+ // line example:
+ // 259:0 rbytes=0 wbytes=12288 rios=0 wios=4 dbytes=0 dios=0
+ for (i = 0; lines[i]; i++) {
+ cols = lxc_string_split_and_trim(lines[i], ' ');
+ if (cols == NULL || lxc_array_len((void **)cols) < 2) {
+ goto err_out;
+ }
+ len = lxc_array_len((void **)cols);
+ for (j = 1; j < len; j++) {
+ kv = lxc_string_split(cols[j], '=');
+ if (kv == NULL || lxc_array_len((void **)kv) != 2) {
+ lxc_free_array((void **)kv, free);
+ continue;
+ }
+ if (is_io_stat_read(kv[0])) {
+ stats->read += strtoull(kv[1], NULL, 0);
+ } else if (is_io_stat_write(kv[0])) {
+ stats->write += strtoull(kv[1], NULL, 0);
+ }
+ lxc_free_array((void **)kv, free);
+ }
+ lxc_free_array((void **)cols, free);
+ }
+
+ stats->total = stats->read + stats->write;
+
+err_out:
+ lxc_free_array((void **)lines, free);
+out:
+ free(buf);
+ return;
+}
+
+static uint64_t metrics_match_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, const char *match, int column)
+{
+#define BUFSIZE 4096
+ char buf[BUFSIZE] = {0};
+ int i = 0;
+ int j = 0;
+ int len = 0;
+ uint64_t val = 0;
+ char **lines = NULL;
+ char **cols = NULL;
+ size_t matchlen = 0;
+
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
+ if (len <= 0) {
+ DEBUG("unable to read cgroup item %s", item);
+ goto err_out;
+ }
+
+ lines = lxc_string_split_and_trim(buf, '\n');
+ if (lines == NULL) {
+ goto err_out;
+ }
+
+ matchlen = strlen(match);
+ for (i = 0; lines[i]; i++) {
+ if (strncmp(lines[i], match, matchlen) != 0) {
+ continue;
+ }
+
+ cols = lxc_string_split_and_trim(lines[i], ' ');
+ if (cols == NULL) {
+ goto err1;
+ }
+ for (j = 0; cols[j]; j++) {
+ if (j == column) {
+ val = strtoull(cols[j], NULL, 0);
+ break;
+ }
+ }
+ lxc_free_array((void **)cols, free);
+ break;
+ }
+err1:
+ lxc_free_array((void **)lines, free);
+err_out:
+ return val;
+}
+
+static bool is_io_stat_rbytes(const char *value)
+{
+ return strcmp(value, "rbytes") == 0;
+}
+
+static bool is_io_stat_wbytes(const char *value)
+{
+ return strcmp(value, "wbytes") == 0;
+}
+
+static bool is_io_stat_rios(const char *value)
+{
+ return strcmp(value, "rios") == 0;
+}
+
+static bool is_io_stat_wios(const char *value)
+{
+ return strcmp(value, "wios") == 0;
+}
+
+static bool unified_metrics_get(struct lxc_container *c, struct cgroup_ops *cgroup_ops, struct lxc_container_metrics *metrics)
+{
+ // cpu
+ metrics->cpu_use_nanos = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "usage_usec", 1) * 1000;
+ metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "user_usec", 1) * 1000;
+ metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "system_usec", 1) * 1000;
+
+ // io
+ metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_service_bytes, is_io_stat_rbytes, is_io_stat_wbytes);
+ metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_serviced, is_io_stat_rios, is_io_stat_wios);
+
+ // memory
+ metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.current");
+ metrics->mem_limit = metrics_get_ull_with_max(c, cgroup_ops, "memory.max");
+ metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "inactive_file", 1);
+ metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "file", 1);
+ metrics->cache_total = metrics->cache;
+
+ // cgroup v2 does not support kernel memory
+ metrics->kmem_used = 0;
+ metrics->kmem_limit = 0;
+
+ // pids
+ metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
+
+ return true;
+}
+
+/* isulad add get container metrics */
+static bool do_lxcapi_get_container_metrics(struct lxc_container *c, struct lxc_container_metrics *metrics)
+{
+ call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
+ const char *state = NULL;
+ if (c == NULL || c->lxc_conf == NULL || metrics == NULL) {
+ return false;
+ }
+
+ state = c->state(c);
+ metrics->state = state;
+
+ if (!is_stopped(c)) {
+ metrics->init = c->init_pid(c);
+ } else {
+ metrics->init = -1;
+ }
+
+ cgroup_ops = cgroup_init(c->lxc_conf);
+ if (cgroup_ops == NULL) {
+ return false;
+ }
+
+ if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_UNIFIED) {
+ return unified_metrics_get(c, cgroup_ops, metrics);
+ }
+
+ metrics->cpu_use_nanos = metrics_get_ull(c, cgroup_ops, "cpuacct.usage");
+ metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
+
+ metrics->rss_bytes = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "rss", 1);
+ metrics->page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgfault", 1);
+ metrics->major_page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgmajfault", 1);
+
+ metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "user", 1);
+ metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "system", 1);
+
+ // Try to read CFQ stats available on all CFQ enabled kernels first
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_serviced_recursive", &metrics->io_serviced);
+ if (metrics->io_serviced.read == 0 && metrics->io_serviced.write == 0 && metrics->io_serviced.total == 0) {
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_service_bytes", &metrics->io_service_bytes);
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_serviced", &metrics->io_serviced);
+ } else {
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_service_bytes_recursive", &metrics->io_service_bytes);
+ }
+
+ metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.usage_in_bytes");
+ metrics->mem_limit = metrics_get_ull(c, cgroup_ops, "memory.limit_in_bytes");
+ metrics->kmem_used = metrics_get_ull(c, cgroup_ops, "memory.kmem.usage_in_bytes");
+ metrics->kmem_limit = metrics_get_ull(c, cgroup_ops, "memory.kmem.limit_in_bytes");
+
+ metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "cache", 1);
+ metrics->cache_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_cache", 1);
+ metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_inactive_file", 1);
+
+ return true;
+}
+
+WRAP_API_1(bool, lxcapi_get_container_metrics, struct lxc_container_metrics *)
+
+#endif
+
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
{
struct lxc_container *c;
@@ -5310,10 +6153,24 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
goto err;
}
+#ifdef HAVE_ISULAD
+ if (!set_oci_hook_config_filename(c)) {
+ fprintf(stderr, "Error allocating oci hooks file pathname\n");
+ goto err;
+ }
+
+ if (load_config && file_exists(c->configfile)) {
+ if (!lxcapi_load_config(c, NULL)) {
+ fprintf(stderr, "Failed to load config for %s\n", name);
+ goto err;
+ }
+ }
+#else
if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) {
fprintf(stderr, "Failed to load config for %s\n", name);
goto err;
}
+#endif
rc = ongoing_create(c);
switch (rc) {
@@ -5337,6 +6194,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c->daemonize = true;
c->pidfile = NULL;
+#ifdef HAVE_ISULAD
+ c->image_type_oci = false;
+#endif
/* Assign the member functions. */
c->is_defined = lxcapi_is_defined;
@@ -5400,6 +6260,20 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
c->umount = lxcapi_umount;
c->seccomp_notify_fd = lxcapi_seccomp_notify_fd;
c->seccomp_notify_fd_active = lxcapi_seccomp_notify_fd_active;
+#ifdef HAVE_ISULAD
+ c->set_container_info_file = lxcapi_set_container_info_file;
+ c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
+ c->add_terminal_fifos = lxcapi_add_terminal_fifo;
+ c->set_terminal_winch = lxcapi_set_terminal_winch;
+ c->set_exec_terminal_winch = lxcapi_set_exec_terminal_winch;
+ c->want_disable_pty = lxcapi_want_disable_pty;
+ c->want_open_stdin = lxcapi_want_open_stdin;
+ c->clean_container_resource = lxcapi_clean_container_resource;
+ c->get_container_pids = lxcapi_get_container_pids;
+ c->set_start_timeout = lxcapi_set_start_timeout;
+ c->set_oci_type = lxcapi_set_oci_type;
+ c->get_container_metrics = lxcapi_get_container_metrics;
+#endif
return c;
@@ -5408,6 +6282,19 @@ err:
return NULL;
}
+#ifdef HAVE_ISULAD
+// isulad: new container without load config to save time
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath)
+{
+ return do_lxc_container_new(name, configpath, false);
+}
+
+struct lxc_container *lxc_container_new(const char *name, const char *configpath)
+{
+ return do_lxc_container_new(name, configpath, true);
+}
+#endif
+
int lxc_get_wait_states(const char **states)
{
int i;
@@ -5578,11 +6465,21 @@ int list_active_containers(const char *lxcpath, char ***nret,
continue;
}
+#ifdef HAVE_ISULAD
+ if (ct_name && ct_name_cnt) {
+ if (array_contains(&ct_name, p, ct_name_cnt)) {
+ if (is_hashed)
+ free(p);
+ continue;
+ }
+ }
+#else
if (array_contains(&ct_name, p, ct_name_cnt)) {
if (is_hashed)
free(p);
continue;
}
+#endif
if (!add_to_array(&ct_name, p, ct_name_cnt)) {
if (is_hashed)
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 3386bff..06e8f0b 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -26,6 +26,10 @@ extern "C" {
#define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */
#define LXC_MOUNT_API_V1 1
+#ifdef HAVE_ISULAD
+#define LXC_IMAGE_OCI_KEY "lxc.imagetype.oci"
+#endif
+
struct bdev_specs;
struct lxc_snapshot;
@@ -40,6 +44,44 @@ struct lxc_mount {
int version;
};
+#ifdef HAVE_ISULAD
+struct lxc_blkio_metrics {
+ uint64_t read;
+ uint64_t write;
+ uint64_t total;
+};
+
+struct lxc_container_metrics {
+ /* State of container */
+ const char *state;
+ /* The process ID of the init container */
+ pid_t init;
+ /* Current pids */
+ uint64_t pids_current;
+ /* CPU usage */
+ uint64_t cpu_use_nanos;
+ uint64_t cpu_use_user;
+ uint64_t cpu_use_sys;
+ /* BlkIO usage */
+ struct lxc_blkio_metrics io_service_bytes;
+ struct lxc_blkio_metrics io_serviced;
+ /* Memory usage */
+ uint64_t mem_used;
+ uint64_t mem_limit;
+ uint64_t rss_bytes;
+ uint64_t page_faults;
+ uint64_t major_page_faults;
+ /* Kernel Memory usage */
+ uint64_t kmem_used;
+ uint64_t kmem_limit;
+ /* Cache usage */
+ uint64_t cache;
+ uint64_t cache_total;
+ /* total inactive file */
+ uint64_t inactive_file_total;
+};
+#endif
+
/*!
* An LXC container.
*
@@ -107,6 +149,38 @@ struct lxc_container {
/*! Full path to configuration file */
char *config_path;
+#ifdef HAVE_ISULAD
+ /*! isulad:
+ * \private
+ * exit FIFO File to open used monitor the state of lxc monitor process.
+ */
+ char *exit_fifo;
+ /*! Whether container wishes to create pty or pipes for console log */
+ bool disable_pty;
+
+ /*! Whether container wishes to keep stdin active */
+ bool open_stdin;
+
+ /*!
+ * \private
+ * isulad: support oci hook from json file
+ * full path of json file
+ * */
+ char *ocihookfile;
+
+ /*! isulad:
+ * \private
+ * start_timeout.
+ */
+ unsigned int start_timeout;
+
+ /*! isulad:
+ * \private
+ * image_type_oci
+ */
+ bool image_type_oci;
+#endif
+
/*!
* \brief Determine if \c /var/lib/lxc/$name/config exists.
*
@@ -884,6 +958,115 @@ struct lxc_container {
* \return Mount fd of the container's devpts instance.
*/
int (*devpts_fd)(struct lxc_container *c);
+
+#ifdef HAVE_ISULAD
+ /*! isulad add
+ * \brief An API call to set the path of info file
+ *
+ * \param c Container.
+ * \param info_file Value of the path of info file.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_container_info_file) (struct lxc_container *c, const char *info_file);
+
+ /*! isulad add
+ * \brief An API call to change the path of the console default fifos
+ *
+ * \param c Container.
+ * \param path Value of the console path.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
+
+ /*! isulad add
+ * \brief An API call to add the path of terminal fifos
+ *
+ * \param c Container.
+ * \param path Value of the console path..
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
+
+ bool (*set_terminal_winch)(struct lxc_container *c, unsigned int height, unsigned int width);
+
+ bool (*set_exec_terminal_winch)(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width);
+
+ /*!
+ * \brief Change whether the container wants to create pty or pipes
+ * from the console log.
+ *
+ * \param c Container.
+ * \param state Value for the disable pty bit (0 or 1).
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*want_disable_pty)(struct lxc_container *c, bool state);
+
+ /*!
+ * \brief Change whether the container wants to keep stdin active
+ * for parent process of container
+ *
+ * \param c Container.
+ * \param state Value for the open_stdin bit (0 or 1).
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*want_open_stdin)(struct lxc_container *c, bool state);
+
+ /*! isulad add
+ * \brief An API call to clean resources of container
+ *
+ * \param c Container.
+ * \param pid Value of container process.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*clean_container_resource) (struct lxc_container *c, pid_t pid);
+
+ /*! isulad add
+ * \brief An API call to get container pids
+ *
+ * \param c Container.
+ * \param pids Value of container pids.
+ * \param pids_len Value of container pids len.
+ * \param pid Value of container pid.
+ * \return \c true on success, else \c false.
+ */
+ bool (*get_container_pids)(struct lxc_container *c,pid_t **pids,size_t *pids_len);
+
+ /*! isulad add
+ * \brief An API call to set start timeout
+ *
+ * \param c Container.
+ * \param start_timeout Value of start timeout.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout);
+
+ /*! isulad add
+ * \brief An API call to set oci type
+ *
+ * \param c Container.
+ * \param image_type_oci image oci type.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_oci_type)(struct lxc_container *c, bool image_type_oci);
+
+ /*! isulad add
+ * \brief An API call to set start timeout
+ *
+ * \param c Container.
+ * \param start_timeout Value of start timeout.
+ *
+ * \return \c true on success, else \c false.
+ */
+ bool (*get_container_metrics)(struct lxc_container *c, struct lxc_container_metrics *metrics);
+#endif
};
/*!
@@ -1017,6 +1200,20 @@ struct lxc_console_log {
*/
struct lxc_container *lxc_container_new(const char *name, const char *configpath);
+#ifdef HAVE_ISULAD
+/*!
+ * \brief Create a new container without loading config.
+ *
+ * \param name Name to use for container.
+ * \param configpath Full path to configuration file to use.
+ *
+ * \return Newly-allocated container, or \c NULL on error.
+ *
+ * \note This function can only used for listing container.
+ */
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath);
+#endif
+
/*!
* \brief Add a reference to the specified container.
*
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 9f68304..70af128 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -344,7 +344,11 @@ static int setup_signal_fd(sigset_t *oldmask)
{
int ret;
sigset_t mask;
+#ifdef HAVE_ISULAD
+ const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH, SIGTERM};
+#else
const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH};
+#endif
/* Block everything except serious error signals. */
ret = sigfillset(&mask);
@@ -625,6 +629,16 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
TRACE("Mainloop is ready");
+#ifdef HAVE_ISULAD
+ // iSulad: close stdin pipe if we do not want open_stdin with container stdin
+ if (!handler->conf->console.open_stdin) {
+ if (handler->conf->console.pipes[0][1] > 0) {
+ close(handler->conf->console.pipes[0][1]);
+ handler->conf->console.pipes[0][1] = -1;
+ }
+ }
+#endif
+
ret = lxc_mainloop(&descr, -1);
if (descr.type == LXC_MAINLOOP_EPOLL)
close_prot_errno_disarm(descr.epfd);
@@ -634,7 +648,11 @@ int lxc_poll(const char *name, struct lxc_handler *handler)
if (console) {
ret = lxc_terminal_mainloop_add(&descr_console, console);
if (ret == 0)
+#ifdef HAVE_ISULAD
+ ret = isulad_safe_mainloop(&descr_console, 100);
+#else
ret = lxc_mainloop(&descr_console, 0);
+#endif
}
out_mainloop_console:
@@ -718,6 +736,12 @@ struct lxc_handler *lxc_init_handler(struct lxc_handler *old,
}
handler->name = name;
+
+#ifdef HAVE_ISULAD
+ handler->exit_code = -1; /* isulad: record exit code of container */
+ handler->image_type_oci = false;
+#endif
+
if (daemonize)
handler->transient_pid = lxc_raw_getpid();
else
@@ -768,6 +792,10 @@ int lxc_init(const char *name, struct lxc_handler *handler)
int ret;
const char *loglevel;
struct lxc_conf *conf = handler->conf;
+#ifdef HAVE_ISULAD
+ conf->console.disable_pty = handler->disable_pty;
+ conf->console.open_stdin = handler->open_stdin;
+#endif
handler->monitor_pid = lxc_raw_getpid();
status_fd = open("/proc/self/status", O_RDONLY | O_CLOEXEC);
@@ -908,6 +936,186 @@ void lxc_expose_namespace_environment(const struct lxc_handler *handler)
}
}
+
+#ifdef HAVE_ISULAD
+/* isulad: start timeout thread */
+typedef enum {
+ START_INIT,
+ START_TIMEOUT,
+ START_MAX,
+} start_timeout_t;
+
+static start_timeout_t global_timeout_state = START_INIT;
+static sem_t global_timeout_sem;
+
+struct start_timeout_conf {
+ unsigned int timeout;
+ int errfd;
+};
+
+void trim_line(char *s)
+{
+ size_t len;
+
+ len = strlen(s);
+ while ((len > 1) && (s[len - 1] == '\n'))
+ s[--len] = '\0';
+}
+
+static int _read_procs_file(const char *path, pid_t **pids, size_t *len)
+{
+ FILE *f;
+ char *line = NULL;
+ size_t sz = 0;
+ pid_t *tmp_pids = NULL;
+
+ f = fopen_cloexec(path, "r");
+ if (!f)
+ return -1;
+
+ while (getline(&line, &sz, f) != -1) {
+ pid_t pid;
+ trim_line(line);
+ pid = (pid_t)atoll(line);
+ if (lxc_mem_realloc((void **)&tmp_pids, sizeof(pid_t) * (*len + 1), *pids, sizeof(pid_t) * (*len)) != 0) {
+ free(*pids);
+ *pids = NULL;
+ ERROR("out of memory");
+ free(line);
+ fclose(f);
+ return -1;
+ }
+ *pids = tmp_pids;
+
+ (*pids)[*len] = pid;
+ (*len)++;
+ }
+
+ free(line);
+ fclose(f);
+ return 0;
+}
+
+static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len)
+{
+ struct dirent *direntp = NULL;
+ DIR *dir = NULL;
+ int ret, failed = 0;
+ char pathname[PATH_MAX];
+
+ dir = opendir(dirpath);
+ if (dir == NULL) {
+ WARN("Failed to open \"%s\"", dirpath);
+ return 0;
+ }
+
+ while ((direntp = readdir(dir))) {
+ struct stat mystat;
+ int rc;
+
+ if (!strcmp(direntp->d_name, ".") ||
+ !strcmp(direntp->d_name, ".."))
+ continue;
+
+ rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name);
+ if (rc < 0 || rc >= PATH_MAX) {
+ failed = 1;
+ continue;
+ }
+
+ if (strcmp(direntp->d_name, "cgroup.procs") == 0) {
+ if (_read_procs_file(pathname, pids, len)) {
+ failed = 1;
+
+ }
+ continue;
+ }
+
+ ret = lstat(pathname, &mystat);
+ if (ret) {
+ failed = 1;
+ continue;
+ }
+
+ if (S_ISDIR(mystat.st_mode)) {
+ if (_recursive_read_cgroup_procs(pathname, pids, len) < 0)
+ failed = 1;
+ }
+ }
+
+ ret = closedir(dir);
+ if (ret) {
+ WARN("Failed to close directory \"%s\"", dirpath);
+ failed = 1;
+ }
+
+ return failed ? -1 : 0;
+}
+
+int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len)
+{
+ const char *devices_path = NULL;
+
+ devices_path = cg_ops->get_cgroup_full_path(cg_ops, "devices");
+ if (!file_exists(devices_path)) {
+ return 0;
+ }
+
+ return _recursive_read_cgroup_procs(devices_path, pids, len);
+}
+
+static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value)
+{
+ char *fullpath;
+ int ret;
+
+ fullpath = must_make_path(cg_ops->get_cgroup_full_path(cg_ops, "freezer"), "freezer.state", NULL);
+ ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666);
+ free(fullpath);
+ return ret;
+}
+
+/* isulad: kill all process in container cgroup path */
+static void signal_all_processes(struct lxc_handler *handler)
+{
+ int ret;
+ struct cgroup_ops *cg_ops = handler->cgroup_ops;
+ pid_t *pids = NULL;
+ size_t len = 0, i;
+
+ ret = set_cgroup_freezer(cg_ops, "FROZEN");
+ if (ret < 0 && errno != ENOENT) {
+ WARN("cgroup_set frozen failed");
+ }
+
+ ret = get_all_pids(cg_ops, &pids, &len);
+ if (ret < 0) {
+ WARN("failed to get all pids");
+ }
+
+ for (i = 0; i < len; i++) {
+ ret = kill(pids[i], SIGKILL);
+ if (ret < 0 && errno != ESRCH) {
+ WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name);
+ }
+ }
+
+ ret = set_cgroup_freezer(cg_ops, "THAWED");
+ if (ret < 0 && errno != ENOENT) {
+ WARN("cgroup_set thawed failed");
+ }
+
+ for (i = 0; i < len; i++) {
+ ret = lxc_wait_for_pid_status(pids[i]);
+ if (ret < 0 && errno != ECHILD) {
+ WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno));
+ }
+ }
+
+ free(pids);
+}
+#endif
+
void lxc_end(struct lxc_handler *handler)
{
int ret;
@@ -945,14 +1153,44 @@ void lxc_end(struct lxc_handler *handler)
handler->lsm_ops->cleanup(handler->lsm_ops, handler->conf, handler->lxcpath);
+
+#ifdef HAVE_ISULAD
+ // close maincmd fd before destroy cgroup for isulad
+ if (handler->conf->reboot == REBOOT_NONE) {
+ /* For all new state clients simply close the command socket.
+ * This will inform all state clients that the container is
+ * STOPPED and also prevents a race between a open()/close() on
+ * the command socket causing a new process to get ECONNREFUSED
+ * because we haven't yet closed the command socket.
+ */
+ close_prot_errno_disarm(handler->conf->maincmd_fd);
+ TRACE("Closed command socket");
+ }
+ int retry_count = 0;
+ int max_retry = 10;
+retry:
+ if (cgroup_ops != NULL && !cgroup_ops->payload_destroy(cgroup_ops, handler)) {
+ TRACE("Trying to kill all subprocess");
+ signal_all_processes(handler);
+ TRACE("Finished kill all subprocess");
+ if (retry_count < max_retry) {
+ usleep(100 * 1000); /* 100 millisecond */
+ retry_count++;
+ goto retry;
+ }
+ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
+ }
+#else
if (cgroup_ops) {
cgroup_ops->payload_destroy(cgroup_ops, handler);
cgroup_ops->monitor_destroy(cgroup_ops, handler);
}
+#endif
put_lxc_rootfs(&handler->conf->rootfs, true);
if (handler->conf->reboot == REBOOT_NONE) {
+#ifndef HAVE_ISULAD
/* For all new state clients simply close the command socket.
* This will inform all state clients that the container is
* STOPPED and also prevents a race between a open()/close() on
@@ -961,12 +1199,23 @@ void lxc_end(struct lxc_handler *handler)
*/
close_prot_errno_disarm(handler->conf->maincmd_fd);
TRACE("Closed command socket");
+#endif
/* This function will try to connect to the legacy lxc-monitord
* state server and only exists for backwards compatibility.
*/
lxc_monitor_send_state(name, STOPPED, handler->lxcpath);
+#ifdef HAVE_ISULAD
+ /* isuald: write exit code to exit fifo */
+ if (handler->conf->exit_fd >= 0) {
+ ret = write(handler->conf->exit_fd, &handler->exit_code, sizeof(int));
+ if (ret != sizeof(int)) {
+ SYSERROR("Failed to write to exit code to exit fifo.");
+ }
+ }
+#endif
+
/* The command socket is closed so no one can acces the command
* socket anymore so there's no need to lock it.
*/
@@ -1060,6 +1309,25 @@ static int do_start(void *data)
lxc_sync_fini_parent(handler);
+#ifdef HAVE_ISULAD
+ sigset_t mask;
+
+ /*isulad: restore default signal handlers and unblock all signals*/
+ for (int i = 1; i < NSIG; i++)
+ signal(i, SIG_DFL);
+
+ ret = sigfillset(&mask);
+ if (ret < 0) {
+ SYSERROR("Failed to fill signal mask");
+ goto out_warn_father;
+ }
+ ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ if (ret < 0) {
+ SYSERROR("Failed to set signal mask");
+ goto out_warn_father;
+ }
+#endif
+
if (lxc_abstract_unix_recv_one_fd(data_sock1, &status_fd, NULL, 0) < 0) {
ERROR("Failed to receive status file descriptor from parent process");
goto out_warn_father;
@@ -1153,7 +1421,11 @@ static int do_start(void *data)
* means that migration won't work, but at least we won't spew output
* where it isn't wanted.
*/
+#ifdef HAVE_ISULAD
+ if (!handler->disable_pty && handler->daemonize && !handler->conf->autodev) {
+#else
if (handler->daemonize && !handler->conf->autodev) {
+#endif
char path[PATH_MAX];
ret = strnprintf(path, sizeof(path), "%s/dev/null",
@@ -1269,6 +1541,9 @@ static int do_start(void *data)
/* Setup the container, ip, names, utsname, ... */
ret = lxc_setup(handler);
if (ret < 0) {
+#ifdef HAVE_ISULAD
+ lxc_write_error_message(handler->conf->errpipe[1], "Failed to setup lxc, please check the config file.");
+#endif
ERROR("Failed to setup container \"%s\"", handler->name);
goto out_warn_father;
}
@@ -1291,6 +1566,43 @@ static int do_start(void *data)
DEBUG("Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges");
}
+#ifdef HAVE_ISULAD
+ /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */
+ if (handler->disable_pty) {
+ if (handler->conf->console.pipes[0][1] >= 0) {
+ close(handler->conf->console.pipes[0][1]);
+ handler->conf->console.pipes[0][1] = -1;
+ }
+
+ if (handler->conf->console.pipes[0][0] >= 0) {
+ ret = dup2(handler->conf->console.pipes[0][0], STDIN_FILENO);
+ if (ret < 0)
+ goto out_warn_father;
+ }
+
+ if (handler->conf->console.pipes[1][0] >= 0) {
+ close(handler->conf->console.pipes[1][0]);
+ handler->conf->console.pipes[1][0] = -1;
+ }
+
+ if (handler->conf->console.pipes[1][1] >= 0) {
+ ret = dup2(handler->conf->console.pipes[1][1], STDOUT_FILENO);
+ if (ret < 0)
+ goto out_warn_father;
+ }
+ if (handler->conf->console.pipes[2][0] >= 0) {
+ close(handler->conf->console.pipes[2][0]);
+ handler->conf->console.pipes[2][0] = -1;
+ }
+
+ if (handler->conf->console.pipes[2][1] >= 0) {
+ ret = dup2(handler->conf->console.pipes[2][1], STDERR_FILENO);
+ if (ret < 0)
+ goto out_warn_father;
+ }
+ }
+#endif
+
/* If we mounted a temporary proc, then unmount it now. */
tmp_proc_unmount(handler->conf);
@@ -1307,7 +1619,11 @@ static int do_start(void *data)
close_prot_errno_disarm(handler->sigfd);
+#ifdef HAVE_ISULAD
+ if (!handler->disable_pty && handler->conf->console.pty < 0 && handler->daemonize) {
+#else
if (handler->conf->console.pty < 0 && handler->daemonize) {
+#endif
if (devnull_fd < 0) {
devnull_fd = open_devnull();
if (devnull_fd < 0)
@@ -1326,6 +1642,16 @@ static int do_start(void *data)
setsid();
if (handler->conf->init_cwd) {
+#ifdef HAVE_ISULAD
+ /* try to craete workdir if not exist */
+ struct stat st;
+ if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) {
+ SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd);
+ lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.",
+ __FILE__, __LINE__, strerror(errno));
+ goto out_warn_father;
+ }
+#endif
ret = chdir(handler->conf->init_cwd);
if (ret < 0) {
SYSERROR("Could not change directory to \"%s\"",
@@ -1372,12 +1698,26 @@ static int do_start(void *data)
}
}
+#ifdef HAVE_ISULAD
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ SYSERROR("Failed to keep permitted capabilities");
+ goto out_warn_father;
+ }
+#endif
+
/* The container has been setup. We can now switch to an unprivileged
* uid/gid.
*/
new_uid = handler->conf->init_uid;
new_gid = handler->conf->init_gid;
+#ifdef HAVE_ISULAD
+ // isulad: set env home in container, must before "Avoid unnecessary syscalls."
+ if (lxc_setup_env_home(new_uid) < 0) {
+ goto out_warn_father;
+ }
+#endif
+
/* Avoid unnecessary syscalls. */
if (new_uid == nsuid)
new_uid = LXC_INVALID_UID;
@@ -1419,6 +1759,19 @@ static int do_start(void *data)
goto out_warn_father;
}
+#ifdef HAVE_ISULAD
+ /* isulad: drop the cap of current process */
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
+ SYSERROR("Failed to clear permitted capabilities");
+ goto out_warn_father;
+ }
+
+ if (lxc_drop_caps(handler->conf)) {
+ SYSERROR("Failed to drop caps");
+ goto out_warn_father;
+ }
+#endif
+
if (handler->conf->monitor_signal_pdeath != SIGKILL) {
ret = lxc_set_death_signal(handler->conf->monitor_signal_pdeath,
handler->monitor_pid, status_fd);
@@ -1433,7 +1786,12 @@ static int do_start(void *data)
* After this call, we are in error because this ops should not return
* as it execs.
*/
+#ifdef HAVE_ISULAD
+ close_prot_errno_disarm(status_fd);
+ handler->ops->start(handler, handler->data, handler->daemonize ? handler->conf->errpipe[1] : -1);
+#else
handler->ops->start(handler, handler->data);
+#endif
out_warn_father:
/*
@@ -1604,6 +1962,94 @@ static inline void resolve_cgroup_clone_flags(struct lxc_handler *handler)
handler->ns_unshare_flags |= CLONE_NEWCGROUP;
}
+#ifdef HAVE_ISULAD
+static int lxc_write_container_info(char *filename, pid_t pid, pid_t p_pid,
+ unsigned long long start_at, unsigned long long p_start_at)
+{
+ FILE *pid_fp = NULL;
+ int ret = 0;
+
+ pid_fp = lxc_fopen(filename, "w");
+ if (pid_fp == NULL) {
+ SYSERROR("Failed to create pidfile '%s'",filename);
+ ret = -1;
+ goto out;
+ }
+
+ if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) {
+ SYSERROR("Failed to write '%s'", filename);
+ ret = -1;
+ goto out;
+ }
+out:
+ if (pid_fp)
+ fclose(pid_fp);
+ pid_fp = NULL;
+ return ret;
+}
+
+static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid,
+ unsigned long long start_at, unsigned long long p_start_at)
+{
+ int ret = 0;
+ int num;
+ char sbuf[1024] = {0}; /* bufs for stat */
+ int saved_pid; /* process id */
+ int saved_ppid; /* pid of parent process */
+ unsigned long long saved_start_time; /* start time of process -- seconds since 1-1-70 */
+ unsigned long long saved_pstart_time; /* start time of parent process -- seconds since 1-1-70 */
+
+ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) {
+ SYSERROR("Failed to read pidfile %s", filename);
+ ret = -1;
+ goto out;
+ }
+
+ num = sscanf(sbuf, "%d %Lu %d %Lu", &saved_pid, &saved_start_time, &saved_ppid, &saved_pstart_time);
+ if (num != 4) {
+ SYSERROR("Call sscanf error");
+ ret = -1;
+ goto out;
+ }
+
+ if (pid != saved_pid || p_pid != saved_ppid
+ || start_at != saved_start_time || p_start_at != saved_pstart_time) {
+ ERROR("Check container info failed");
+ ret = -1;
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+/* isuald: save pid/ppid info */
+static int lxc_save_container_info(char *filename, pid_t pid)
+{
+ int ret = 0;
+ pid_t p_pid = 0;
+ unsigned long long start_at = 0;
+ unsigned long long p_start_at = 0;
+
+ start_at = lxc_get_process_startat(pid);
+ p_pid = getpid();
+ p_start_at = lxc_get_process_startat(p_pid);
+
+ ret = lxc_write_container_info(filename, pid, p_pid, start_at, p_start_at);
+ if (ret != 0) {
+ goto out;
+ }
+
+ ret = lxc_check_container_info(filename, pid, p_pid, start_at, p_start_at);
+ if (ret != 0) {
+ goto out;
+ }
+
+out:
+ return ret;
+}
+#endif
+
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
* exec()s the requested container binary.
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed
@@ -1741,6 +2187,32 @@ static int lxc_spawn(struct lxc_handler *handler)
handler->clone_flags &= ~CLONE_PIDFD;
TRACE("Cloned child process %d", handler->pid);
+#ifdef HAVE_ISULAD
+ /* isulad: close pipe after clone */
+ if (handler->conf->console.pipes[0][0] >= 0) {
+ close(handler->conf->console.pipes[0][0]);
+ handler->conf->console.pipes[0][0] = -1;
+ }
+
+ if (handler->conf->console.pipes[1][1] >= 0) {
+ close(handler->conf->console.pipes[1][1]);
+ handler->conf->console.pipes[1][1] = -1;
+ }
+
+ if (handler->conf->console.pipes[2][1] >= 0) {
+ close(handler->conf->console.pipes[2][1]);
+ handler->conf->console.pipes[2][1] = -1;
+ }
+
+ /* isulad: save pid/ppid info into file*/
+ if (handler->conf->container_info_file) {
+ if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) {
+ ERROR("Failed to save cloned container pid");
+ goto out_delete_net;
+ }
+ }
+#endif
+
ret = core_scheduling(handler);
if (ret < 0)
goto out_delete_net;
@@ -1757,6 +2229,13 @@ static int lxc_spawn(struct lxc_handler *handler)
if (ret < 0)
SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr);
+#ifdef HAVE_ISULAD
+ if (handler->cgroup_ops->container_cgroup) {
+ if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1))
+ SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup);
+ }
+#endif
+
for (i = 0; i < LXC_NS_MAX; i++)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
INFO("Cloned %s", ns_info[i].flag_name);
@@ -1848,7 +2327,11 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net;
}
+#ifdef HAVE_ISULAD
+ ret = setup_resource_limits(conf, handler->pid, conf->errpipe[1]);
+#else
ret = setup_resource_limits(conf, handler->pid);
+#endif
if (ret < 0) {
ERROR("Failed to setup resource limits");
goto out_delete_net;
@@ -1911,6 +2394,27 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net;
}
+#ifdef HAVE_ISULAD
+ /* isulad: Run oci prestart hook at here */
+ ret = run_oci_hooks(name, "oci-prestart", conf, lxcpath);
+ if (ret < 0) {
+ ERROR("Failed to run oci prestart hooks");
+ goto out_delete_net;
+ }
+
+ if (START_TIMEOUT == global_timeout_state) {
+ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
+ ERROR("Starting the container \"%s\" timeout.", name);
+ goto out_delete_net;
+ }
+
+ /* Tell the child to continue its initialization. We'll get
+ * LXC_SYNC_POST_OCI_PRESTART_HOOK when it is ready for us to run oci prestart hooks.
+ */
+ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_OCI_PRESTART_HOOK))
+ goto out_delete_net;
+#endif
+
if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
goto out_delete_net;
@@ -1969,6 +2473,22 @@ static int lxc_spawn(struct lxc_handler *handler)
if (ret < 0)
goto out_abort;
+#ifdef HAVE_ISULAD
+ /* isulad: Run oci prestart hook at here */
+ ret = run_oci_hooks(name, "oci-poststart", conf, lxcpath);
+ if (ret < 0) {
+ ERROR("Failed to run oci poststart hooks");
+ goto out_abort;
+ }
+
+ if (START_TIMEOUT == global_timeout_state) {
+ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
+ ERROR("Starting the container \"%s\" timeout.", name);
+ goto out_abort;
+ }
+
+#endif
+
ret = lxc_set_state(name, handler, RUNNING);
if (ret < 0) {
ERROR("Failed to set state to \"%s\"", lxc_state2str(RUNNING));
@@ -2014,9 +2534,82 @@ static int lxc_inherit_namespaces(struct lxc_handler *handler)
return 0;
}
+#ifdef HAVE_ISULAD
+/* isulad: start timeout thread function */
+static void* wait_start_timeout(void *arg)
+{
+ struct start_timeout_conf *conf = (struct start_timeout_conf *)arg;
+
+ sem_post(&global_timeout_sem);
+
+ if (!conf || conf->timeout < 1)
+ goto out;
+
+ sleep(conf->timeout);
+
+ global_timeout_state = START_TIMEOUT;
+
+out:
+ free(conf);
+ return ((void *)0);
+}
+
+/* isulad: create start timeout thread */
+static int create_start_timeout_thread(struct lxc_conf *conf, unsigned int start_timeout)
+{
+ int ret = 0;
+ pthread_t ptid;
+ pthread_attr_t attr;
+ struct start_timeout_conf *timeout_conf = NULL;
+
+ if (sem_init(&global_timeout_sem, 0, 0)) {
+ ERROR("Failed to init start timeout semaphore");/*lint !e613*/
+ ret = -1;
+ return ret;
+ }
+
+ timeout_conf = malloc(sizeof(struct start_timeout_conf));
+ if (timeout_conf == NULL) {
+ ERROR("Failed to malloc start timeout conf");
+ ret = -1;
+ goto out;
+ }
+
+ memset(timeout_conf, 0, sizeof(struct start_timeout_conf));
+ timeout_conf->errfd = conf->errpipe[1];
+ timeout_conf->timeout = start_timeout;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ret = pthread_create(&ptid, &attr, wait_start_timeout, timeout_conf);
+ pthread_attr_destroy(&attr);
+ if (ret != 0) {
+ ERROR("Create start wait timeout thread failed");
+ free(timeout_conf);
+ goto out;
+ }
+
+ sem_wait(&global_timeout_sem);
+out:
+ sem_destroy(&global_timeout_sem);
+ return ret;
+}
+
+// isulad: send '128 + signal' if container is killed by signal.
+#define EXIT_SIGNAL_OFFSET 128
+#endif
+
+#ifdef HAVE_ISULAD
+int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
+ void *data, const char *lxcpath, bool daemonize, int *error_num,
+ unsigned int start_timeout)
+{
+ int exit_code;
+#else
int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
void *data, const char *lxcpath, bool daemonize, int *error_num)
{
+#endif
int ret, status;
const char *name = handler->name;
struct lxc_conf *conf = handler->conf;
@@ -2032,6 +2625,17 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
handler->daemonize = daemonize;
cgroup_ops = handler->cgroup_ops;
+#ifdef HAVE_ISULAD
+ /* isulad: add start timeout limit */
+ if (start_timeout > 0) {
+ ret = create_start_timeout_thread(conf, start_timeout);
+ if (ret) {
+ ERROR("Failed to create start timeout thread for container \"%s\".", name);
+ goto out_abort;
+ }
+ }
+#endif
+
if (!attach_block_device(handler->conf)) {
ERROR("Failed to attach block device");
ret = -1;
@@ -2116,11 +2720,13 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
goto out_delete_network;
}
+#ifndef HAVE_ISULAD
if (!handler->init_died && handler->pid > 0) {
ERROR("Child process is not killed");
ret = -1;
goto out_delete_network;
}
+#endif
status = lxc_wait_for_pid_status(handler->pid);
if (status < 0)
@@ -2130,6 +2736,20 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
* reboot. This should mean it was an lxc-execute which simply exited.
* In any case, treat it as a 'halt'.
*/
+#ifdef HAVE_ISULAD
+ // isulad: recored log for container init exit
+ if (WIFSIGNALED(status)) {
+ int signal_nr = WTERMSIG(status);
+ exit_code = EXIT_SIGNAL_OFFSET + signal_nr;
+ ERROR("Container \"%s\" init exited with signal %d", name, signal_nr);
+ } else if (WIFEXITED(status)) {
+ exit_code = WEXITSTATUS(status);
+ ERROR("Container \"%s\" init exited with status %d", name, exit_code);
+ } else {
+ exit_code = -1;
+ ERROR("Container \"%s\" init exited with unknown status", name);
+ }
+#else
if (WIFSIGNALED(status)) {
int signal_nr = WTERMSIG(status);
switch(signal_nr) {
@@ -2148,16 +2768,25 @@ int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
break;
}
}
+#endif
ret = lxc_restore_phys_nics_to_netns(handler);
if (ret < 0)
ERROR("Failed to move physical network devices back to parent network namespace");
+#ifdef HAVE_ISULAD
+ lxc_monitor_send_exit_code(name, exit_code, handler->lxcpath);
+#else
lxc_monitor_send_exit_code(name, status, handler->lxcpath);
+#endif
lxc_error_set_and_log(handler->pid, status);
if (error_num)
*error_num = handler->exit_status;
+#ifdef HAVE_ISULAD
+ handler->exit_code = exit_code; /* record exit code */
+#endif
+
lxc_delete_network(handler);
detach_block_device(handler->conf);
lxc_end(handler);
@@ -2187,7 +2816,11 @@ struct start_args {
char *const *argv;
};
+#ifdef HAVE_ISULAD
+static int start(struct lxc_handler *handler, void* data, int fd)
+#else
static int start(struct lxc_handler *handler, void* data)
+#endif
{
struct start_args *arg = data;
@@ -2195,6 +2828,9 @@ static int start(struct lxc_handler *handler, void* data)
execvp(arg->argv[0], arg->argv);
SYSERROR("Failed to exec \"%s\"", arg->argv[0]);
+#ifdef HAVE_ISULAD
+ lxc_write_error_message(fd, "exec: \"%s\": %s.", arg->argv[0], strerror(errno));
+#endif
return 0;
}
@@ -2212,14 +2848,22 @@ static struct lxc_operations start_ops = {
};
int lxc_start(char *const argv[], struct lxc_handler *handler,
+#ifdef HAVE_ISULAD
+ const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout)
+#else
const char *lxcpath, bool daemonize, int *error_num)
+#endif
{
struct start_args start_arg = {
.argv = argv,
};
TRACE("Doing lxc_start");
+#ifdef HAVE_ISULAD
+ return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num, start_timeout);
+#else
return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num);
+#endif
}
static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
@@ -2291,3 +2935,261 @@ static bool do_destroy_container(struct lxc_handler *handler)
return storage_destroy(handler->conf);
}
+
+#ifdef HAVE_ISULAD
+/*isulad: set env for clean resources */
+static int clean_resource_set_env(struct lxc_handler *handler)
+{
+ const char *name = handler->name;
+ struct lxc_conf *conf = handler->conf;
+ char bufstr[PATH_MAX + 1];
+ int i = 0;
+ int j = 0;
+ int len = 2; //set "LXC_PID" and "LXC_CGNS_AWARE"
+
+ if (conf == NULL || conf->ocihooks == NULL || conf->ocihooks->poststop_len == 0) {
+ return 0;
+ }
+
+ if (name) {
+ len++;
+ }
+ if (conf->rcfile) {
+ len++;
+ }
+ if (conf->rootfs.mount) {
+ len++;
+ }
+ if (conf->rootfs.path) {
+ len++;
+ }
+ if (conf->console.path) {
+ len++;
+ }
+ if (conf->console.log_path) {
+ len++;
+ }
+ if (handler->cgroup_ops->container_cgroup) {
+ len++;
+ }
+
+ for (; i < conf->ocihooks->poststop_len; i++) {
+ size_t cap = conf->ocihooks->poststop[i]->env_len;
+ size_t newcap = cap + len + 1;
+ if (lxc_grow_array((void ***)&(conf->ocihooks->poststop[i]->env), &cap, newcap, 1) != 0) {
+ return -1;
+ }
+ j = conf->ocihooks->poststop[i]->env_len;
+ /* Start of environment variable setup for hooks. */
+ if (name) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_NAME=%s", name);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ if (conf->rcfile) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONFIG_FILE=%s", conf->rcfile);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ if (conf->rootfs.mount) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ if (conf->rootfs.path) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_PATH=%s", conf->rootfs.path);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ if (conf->console.path) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE=%s", conf->console.path);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ if (conf->console.log_path) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup("LXC_CGNS_AWARE=1");
+
+ snprintf(bufstr, PATH_MAX + 1, "LXC_PID=%d", handler->pid);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ if (handler->cgroup_ops->container_cgroup) {
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CGROUP_PATH=%s", handler->cgroup_ops->container_cgroup);
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
+ }
+ conf->ocihooks->poststop[i]->env_len = j;
+ /* End of environment variable setup for hooks. */
+ }
+ return 0;
+}
+
+/*isulad: init handler for clean */
+static struct lxc_handler *lxc_init_clean_handler(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
+{
+ int i;
+ struct lxc_handler *handler;
+
+ handler = malloc(sizeof(*handler));
+ if (handler == NULL)
+ return NULL;
+
+ memset(handler, 0, sizeof(*handler));
+
+ /* Note that am_guest_unpriv() checks the effective uid. We
+ * probably don't care if we are real root only if we are running
+ * as root so this should be fine.
+ */
+ handler->am_root = !am_guest_unpriv();
+ handler->data_sock[0] = handler->data_sock[1] = -1;
+ handler->conf = conf;
+ handler->lxcpath = lxcpath;
+ handler->pinfd = -1;
+ handler->sigfd = -EBADF;
+ handler->pidfd = -EBADF;
+ handler->init_died = false;
+ handler->monitor_status_fd = -EBADF;
+ handler->pid = pid;
+ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
+ if (handler->conf->reboot == REBOOT_NONE)
+ lxc_list_init(&handler->conf->state_clients);
+
+ for (i = 0; i < LXC_NS_MAX; i++)
+ handler->nsfd[i] = -1;
+
+ handler->name = name;
+ handler->exit_code = -1; /* isulad: record exit code of container */
+
+ handler->cgroup_ops = cgroup_init(conf);
+ if (!handler->cgroup_ops) {
+ ERROR("Failed to initialize cgroup driver");
+ goto on_error;
+ }
+
+ INFO("Container \"%s\" 's clean handler is initialized.", name);
+
+ return handler;
+
+on_error:
+ lxc_put_handler(handler);
+
+ return NULL;
+}
+
+/*isulad: init handler for clean */
+static struct lxc_handler *lxc_init_pids_handler(char *name, char *lxcpath, struct lxc_conf *conf)
+{
+ int i;
+ struct lxc_handler *handler;
+
+ handler = malloc(sizeof(*handler));
+ if (handler == NULL)
+ return NULL;
+
+ memset(handler, 0, sizeof(*handler));
+
+ /* Note that am_guest_unpriv() checks the effective uid. We
+ * probably don't care if we are real root only if we are running
+ * as root so this should be fine.
+ */
+ handler->am_root = !am_guest_unpriv();
+ handler->data_sock[0] = handler->data_sock[1] = -1;
+ handler->conf = conf;
+ handler->lxcpath = lxcpath;
+ handler->pinfd = -1;
+ handler->sigfd = -EBADF;
+ handler->init_died = false;
+ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
+ handler->monitor_status_fd = -EBADF;
+ handler->pidfd = -EBADF;
+ if (handler->conf->reboot == REBOOT_NONE)
+ lxc_list_init(&handler->conf->state_clients);
+
+ for (i = 0; i < LXC_NS_MAX; i++)
+ handler->nsfd[i] = -1;
+
+ handler->name = name;
+ handler->exit_code = -1; /* isulad: record exit code of container */
+
+ handler->cgroup_ops = cgroup_init(conf);
+ if (!handler->cgroup_ops) {
+ ERROR("Failed to initialize cgroup driver");
+ goto on_error;
+ }
+
+ INFO("Container \"%s\" 's clean handler is initialized.", name);
+
+ return handler;
+
+on_error:
+ lxc_put_handler(handler);
+
+ return NULL;
+}
+
+/*isulad: do_lxcapi_clean_resource */
+int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
+{
+ int ret = 0;
+ struct lxc_handler *handler = NULL;
+ int retry_count = 0;
+ int max_retry = 10;
+
+ handler = lxc_init_clean_handler(name, lxcpath, conf, pid);
+ if (!handler) {
+ ERROR("Failed to init container %s clean handler", name);
+ ret = -1;
+ goto out;
+ }
+
+ if (clean_resource_set_env(handler) != 0) {
+ ERROR("Failed to set env for poststop hooks");
+ ret = -1;
+ goto out;
+ }
+
+ if (run_oci_hooks(handler->name, "oci-poststop", handler->conf, handler->lxcpath)) {
+ ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name);
+ ret = -1;
+ }
+
+retry:
+ if (!handler->cgroup_ops->payload_destroy(handler->cgroup_ops, handler)) {
+ TRACE("Trying to kill all subprocess");
+ signal_all_processes(handler);
+ TRACE("Finished kill all subprocess");
+ if (retry_count < max_retry) {
+ usleep(100 * 1000); /* 100 millisecond */
+ retry_count++;
+ goto retry;
+ }
+ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
+ ret = -1;
+ }
+
+out:
+ lxc_put_handler(handler);
+ return ret;
+}
+
+/*isulad: do_lxcapi_get_pids */
+int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len)
+{
+ int ret = 0;
+ struct lxc_handler *handler = NULL;
+ struct cgroup_ops *cg_ops = NULL;
+
+ handler = lxc_init_pids_handler(name, lxcpath, conf);
+ if (!handler) {
+ ERROR("Failed to init container %s clean handler", name);
+ ret = -1;
+ goto out;
+ }
+
+ cg_ops = handler->cgroup_ops;
+ ret = get_all_pids(cg_ops, pids, pids_len);
+ if (ret < 0) {
+ WARN("failed to get all pids");
+ }
+
+out:
+ lxc_put_handler(handler);
+ return ret;
+}
+
+#endif
diff --git a/src/lxc/start.h b/src/lxc/start.h
index bbd1a83..d03e5d5 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -153,7 +153,11 @@ struct execute_args {
};
struct lxc_operations {
+#ifdef HAVE_ISULAD
+ int (*start)(struct lxc_handler *, void *, int);
+#else
int (*start)(struct lxc_handler *, void *);
+#endif
int (*post_start)(struct lxc_handler *, void *);
};
@@ -184,12 +188,26 @@ static inline int inherit_fds(struct lxc_handler *handler, bool closeall)
ARRAY_SIZE(handler->keep_fds));
}
+#ifdef HAVE_ISULAD
+__hidden extern int __lxc_start(struct lxc_handler *handler,
+ struct lxc_operations* ops, void *data, const char *lxcpath,
+ bool daemonize, int *error_num, unsigned int start_timeout);
+#else
__hidden extern int __lxc_start(struct lxc_handler *, struct lxc_operations *, void *, const char *,
bool, int *);
+#endif
__hidden extern int resolve_clone_flags(struct lxc_handler *handler);
__hidden extern void lxc_expose_namespace_environment(const struct lxc_handler *handler);
+#ifdef HAVE_ISULAD
+/*isulad: do_lxcapi_clean_resource */
+extern int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid);
+
+/*isulad: do_lxcapi_get_pids */
+extern int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len);
+#endif
+
static inline bool container_uses_namespace(const struct lxc_handler *handler,
unsigned int ns_flag)
{
--
2.25.1
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jchzhou/lxc.git
[email protected]:jchzhou/lxc.git
jchzhou
lxc
lxc
master

搜索帮助