File _service:tar_scm:0004-iSulad-adapt-confile-lxccontainer-and-start.patch of Package lxc
3311
1
From 3e7fb35a35cff34be2bb7ace0b239d540fe0657f Mon Sep 17 00:00:00 2001
2
From: zhangxiaoyu <zhangxiaoyu58@huawei.com>
3
Date: Wed, 26 Jul 2023 14:57:33 +0800
4
Subject: [PATCH] [iSulad] adapt confile lxccontainer and start
5
6
Signed-off-by: zhangxiaoyu <zhangxiaoyu58@huawei.com>
7
---
8
src/lxc/conf.c | 11 -
9
src/lxc/conf.h | 4 -
10
src/lxc/confile.c | 558 +++++++++++++++++++++++++
11
src/lxc/lxccontainer.c | 899 +++++++++++++++++++++++++++++++++++++++-
12
src/lxc/lxccontainer.h | 197 +++++++++
13
src/lxc/start.c | 902 +++++++++++++++++++++++++++++++++++++++++
14
src/lxc/start.h | 18 +
15
7 files changed, 2573 insertions(+), 16 deletions(-)
16
17
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
18
index a0e0375..187e60e 100644
19
--- a/src/lxc/conf.c
20
+++ b/src/lxc/conf.c
21
22
}
23
free(conf->systemd);
24
lxc_clear_init_args(conf);
25
- lxc_clear_init_groups(conf);
26
lxc_clear_populate_devices(conf);
27
lxc_clear_rootfs_masked_paths(conf);
28
lxc_clear_rootfs_ro_paths(conf);
29
30
return 0;
31
}
32
33
-/*isulad clear init groups*/
34
-int lxc_clear_init_groups(struct lxc_conf *lxc_conf)
35
-{
36
- free(lxc_conf->init_groups);
37
- lxc_conf->init_groups = NULL;
38
- lxc_conf->init_groups_len = 0;
39
-
40
- return 0;
41
-}
42
-
43
/*isulad: clear populate devices*/
44
int lxc_clear_populate_devices(struct lxc_conf *c)
45
{
46
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
47
index 683b8ba..108e05b 100644
48
--- a/src/lxc/conf.h
49
+++ b/src/lxc/conf.h
50
51
char **init_argv;
52
size_t init_argc;
53
54
- gid_t *init_groups;
55
- size_t init_groups_len;
56
-
57
/* populate devices */
58
struct lxc_list populate_devs;
59
mode_t umask; // umask value
60
61
#ifdef HAVE_ISULAD
62
// isulad add
63
__hidden int lxc_clear_init_args(struct lxc_conf *lxc_conf);
64
-__hidden int lxc_clear_init_groups(struct lxc_conf *lxc_conf);
65
__hidden int lxc_clear_populate_devices(struct lxc_conf *c);
66
__hidden int lxc_clear_rootfs_masked_paths(struct lxc_conf *c);
67
__hidden int lxc_clear_rootfs_ro_paths(struct lxc_conf *c);
68
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
69
index 7966d32..1492776 100644
70
--- a/src/lxc/confile.c
71
+++ b/src/lxc/confile.c
72
73
lxc_config_define(sysctl);
74
lxc_config_define(proc);
75
lxc_config_define(sched_core);
76
+#ifdef HAVE_ISULAD
77
+lxc_config_define(init_args);
78
+lxc_config_define(populate_device);
79
+lxc_config_define(umask);
80
+lxc_config_define(rootfs_masked_paths);
81
+lxc_config_define(rootfs_ro_paths);
82
+lxc_config_define(systemd);
83
+lxc_config_define(console_log_driver);
84
+lxc_config_define(console_syslog_tag);
85
+lxc_config_define(console_syslog_facility);
86
+lxc_config_define(selinux_mount_context);
87
+#endif
88
89
static int set_config_unsupported_key(const char *key, const char *value,
90
struct lxc_conf *lxc_conf, void *data)
91
92
{ "lxc.uts.name", true, set_config_uts_name, get_config_uts_name, clr_config_uts_name, },
93
{ "lxc.sysctl", false, set_config_sysctl, get_config_sysctl, clr_config_sysctl, },
94
{ "lxc.proc", false, set_config_proc, get_config_proc, clr_config_proc, },
95
+#ifdef HAVE_ISULAD
96
+ { "lxc.isulad.init.args", set_config_init_args, get_config_init_args, clr_config_init_args, },
97
+ { "lxc.isulad.populate.device", set_config_populate_device, get_config_populate_device, clr_config_populate_device, },
98
+ { "lxc.isulad.umask", set_config_umask, get_config_umask, clr_config_umask, },
99
+ { "lxc.isulad.rootfs.maskedpaths", set_config_rootfs_masked_paths, get_config_rootfs_masked_paths, clr_config_rootfs_masked_paths, },
100
+ { "lxc.isulad.rootfs.ropaths", set_config_rootfs_ro_paths, get_config_rootfs_ro_paths, clr_config_rootfs_ro_paths, },
101
+ { "lxc.isulad.systemd", set_config_systemd, get_config_systemd, clr_config_systemd, },
102
+ { "lxc.console.logdriver", set_config_console_log_driver, get_config_console_log_driver, clr_config_console_log_driver, },
103
+ { "lxc.console.syslog_tag", set_config_console_syslog_tag, get_config_console_syslog_tag, clr_config_console_syslog_tag, },
104
+ { "lxc.console.syslog_facility", set_config_console_syslog_facility, get_config_console_syslog_facility, clr_config_console_syslog_facility, },
105
+ { "lxc.selinux.mount_context", set_config_selinux_mount_context, get_config_selinux_mount_context, clr_config_selinux_mount_context, },
106
+#endif
107
};
108
109
static struct lxc_config_t unsupported_config_key = {
110
111
if (!new_env)
112
return ret_errno(ENOMEM);
113
114
+#ifdef HAVE_ISULAD
115
+ /* isulad: recover space replaced by SPACE_MAGIC_STR */
116
+ dup = lxc_string_replace(SPACE_MAGIC_STR, " ", value);
117
+#else
118
dup = strdup(value);
119
+#endif
120
if (!dup)
121
return ret_errno(ENOMEM);
122
123
124
if (ret)
125
return ret_errno(EINVAL);
126
127
+#ifndef HAVE_ISULAD
128
+ /* isulad: support rotate muti-files */
129
if (lxc_conf->console.log_rotate > 1)
130
return log_error_errno(-EINVAL, EINVAL, "The \"lxc.console.rotate\" config key can only be set to 0 or 1");
131
+#endif
132
133
return 0;
134
}
135
136
bool from_include;
137
};
138
139
+#ifdef HAVE_ISULAD
140
+// escape_string_decode compress some escape characters
141
+static char *escape_string_decode(const char *src)
142
+{
143
+ size_t src_end = 0;
144
+ size_t dst_end = 0;
145
+ size_t len = 0;
146
+ char *dst = NULL;
147
+
148
+ if (src == NULL) {
149
+ return NULL;
150
+ }
151
+
152
+ len = strlen(src);
153
+ if (len == 0) {
154
+ return NULL;
155
+ }
156
+
157
+ dst = calloc(1, len + 1);
158
+ if (dst == NULL) {
159
+ ERROR("Out of memory");
160
+ return NULL;
161
+ }
162
+
163
+ while(src_end < len) {
164
+ if (src[src_end] == '\\') {
165
+ switch (src[++src_end])
166
+ {
167
+ case 'r': dst[dst_end] = '\r'; break;
168
+ case 'n': dst[dst_end] = '\n'; break;
169
+ case 'f': dst[dst_end] = '\f'; break;
170
+ case 'b': dst[dst_end] = '\b'; break;
171
+ case 't': dst[dst_end] = '\t'; break;
172
+ case '\\': dst[dst_end] = '\\'; break;
173
+ // default do not decode
174
+ default: dst[dst_end++] = '\\'; dst[dst_end] = src[src_end]; break;
175
+ }
176
+ } else {
177
+ dst[dst_end] = src[src_end];
178
+ }
179
+ dst_end++;
180
+ src_end++;
181
+ }
182
+
183
+ return dst;
184
+}
185
+#endif
186
+
187
static int parse_line(char *buffer, void *data)
188
{
189
__do_free char *linep = NULL;
190
191
int ret;
192
char *dup = buffer;
193
struct parse_line_conf *plc = data;
194
+#ifdef HAVE_ISULAD
195
+ __do_free char *value_decode = NULL;
196
+#endif
197
198
if (!plc->conf)
199
return syserror_set(-EINVAL, "Missing config");
200
201
}
202
203
config = lxc_get_config(key);
204
+#ifdef HAVE_ISULAD
205
+ value_decode = escape_string_decode(value);
206
+ if (value_decode == NULL) {
207
+ ERROR("Value %s decode failed", value);
208
+ }
209
+ ret = config->set(key, value_decode ? value_decode: value, plc->conf, NULL);
210
+#else
211
return config->set(key, value, plc->conf, NULL);
212
+#endif
213
}
214
215
static struct new_config_item *parse_new_conf_line(char *buffer)
216
217
218
lxc_list_for_each(it, defines) {
219
struct new_config_item *new_item = it->elem;
220
+#ifdef HAVE_ISULAD
221
+ if (strcmp(new_item->key, LXC_IMAGE_OCI_KEY) == 0) {
222
+ c->set_oci_type(c, true);
223
+ continue;
224
+ }
225
+#endif
226
bret = c->set_config_item(c, new_item->key, new_item->val);
227
if (!bret)
228
break;
229
230
c->sched_core = false;
231
return 0;
232
}
233
+
234
+
235
+#ifdef HAVE_ISULAD
236
+/* isulad: set config for init args */
237
+static int set_config_init_args(const char *key, const char *value,
238
+ struct lxc_conf *lxc_conf, void *data)
239
+{
240
+ int ret = 0;
241
+ char **tmp = NULL;
242
+ char *new_value = NULL;
243
+
244
+ ret = set_config_string_item(&new_value, value);
245
+ if (ret || !new_value)
246
+ return ret;
247
+
248
+ tmp = (char **)realloc(lxc_conf->init_argv, (lxc_conf->init_argc + 1) * sizeof(char *));
249
+ if (!tmp) {
250
+ ERROR("Out of memory");
251
+ free(new_value);
252
+ return -1;
253
+ }
254
+
255
+ lxc_conf->init_argv = tmp;
256
+
257
+ lxc_conf->init_argv[lxc_conf->init_argc] = new_value;
258
+ lxc_conf->init_argc++;
259
+
260
+ return 0;
261
+}
262
+
263
+/* isulad: get config init args */
264
+static int get_config_init_args(const char *key, char *retv, int inlen,
265
+ struct lxc_conf *c, void *data)
266
+{
267
+ int i, len, fulllen = 0;
268
+
269
+ if (!retv)
270
+ inlen = 0;
271
+ else
272
+ memset(retv, 0, inlen);
273
+
274
+ for (i = 0; i < c->init_argc; i++) {
275
+ strprint(retv, inlen, "%s", c->init_argv[i]);
276
+ }
277
+
278
+ return fulllen;
279
+}
280
+
281
+/* isulad: clr config init args*/
282
+static inline int clr_config_init_args(const char *key, struct lxc_conf *c,
283
+ void *data)
284
+{
285
+ return lxc_clear_init_args(c);
286
+}
287
+
288
+/* isulad: set config for populate device */
289
+static int set_config_populate_device(const char *key, const char *value,
290
+ struct lxc_conf *lxc_conf, void *data)
291
+{
292
+ int ret = 0, major = 0, minor = 0;
293
+ uid_t uid = (uid_t)-1;
294
+ gid_t gid = (gid_t)-1;
295
+ char name[4096] = {0}; /* MAX dev path name */
296
+ char type[3] = {0};
297
+ char *replace_value = NULL;
298
+ mode_t filemode = 0;
299
+ struct lxc_list *iter = NULL;
300
+ struct lxc_list *dev_list = NULL;
301
+ struct lxc_populate_devs *dev_elem = NULL;
302
+
303
+ if (lxc_config_value_empty(value))
304
+ return lxc_clear_populate_devices(lxc_conf);
305
+
306
+ /* lxc.populate.device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID
307
+ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
308
+ */
309
+ ret = sscanf(value, "%4095[^:]:%2[^:]:%i:%i:%i:%u:%u", name, type, &major, &minor, &filemode, &uid, &gid);
310
+ if (ret != 7)
311
+ return -1;
312
+
313
+ /* find existing list element */
314
+ lxc_list_for_each(iter, &lxc_conf->populate_devs) {
315
+ dev_elem = iter->elem;
316
+
317
+ if (strcmp(name, dev_elem->name) != 0)
318
+ continue;
319
+
320
+ replace_value = safe_strdup(type);
321
+
322
+ free(dev_elem->type);
323
+ dev_elem->type = replace_value;
324
+ dev_elem->file_mode = filemode;
325
+ dev_elem->maj = major;
326
+ dev_elem->min = minor;
327
+ dev_elem->uid = (uid_t)uid;
328
+ dev_elem->gid = (gid_t)gid;
329
+ return 0;
330
+ }
331
+
332
+ /* allocate list element */
333
+ dev_list = malloc(sizeof(*dev_list));
334
+ if (dev_list == NULL)
335
+ goto on_error;
336
+
337
+ lxc_list_init(dev_list);
338
+
339
+ dev_elem = malloc(sizeof(*dev_elem));
340
+ if (dev_elem == NULL)
341
+ goto on_error;
342
+ memset(dev_elem, 0, sizeof(*dev_elem));
343
+
344
+ dev_elem->name = safe_strdup(name);
345
+
346
+ dev_elem->type = safe_strdup(type);
347
+
348
+ dev_elem->file_mode = filemode;
349
+ dev_elem->maj = major;
350
+ dev_elem->min = minor;
351
+ dev_elem->uid = (uid_t)uid;
352
+ dev_elem->gid = (gid_t)gid;
353
+
354
+ lxc_list_add_elem(dev_list, dev_elem);
355
+
356
+ lxc_list_add_tail(&lxc_conf->populate_devs, dev_list);
357
+
358
+ return 0;
359
+
360
+on_error:
361
+ free(dev_list);
362
+ if (dev_elem) {
363
+ free(dev_elem->name);
364
+ free(dev_elem->type);
365
+ free(dev_elem);
366
+ }
367
+ return -1;
368
+}
369
+
370
+/* isulad: get config populate device
371
+ * If you ask for 'lxc.populate.device', then all populate device
372
+ * entries will be printed, in 'lxc.populate.device = path_in_container:type:major:minor:mode:uid:gid' format.
373
+ * For e.g. lxc.populate.device = /dev/sda:b:8:0:0666:0:0
374
+ */
375
+static int get_config_populate_device(const char *key, char *retv, int inlen,
376
+ struct lxc_conf *c, void *data)
377
+{
378
+ int len;
379
+ struct lxc_list *it = NULL;
380
+ int fulllen = 0;
381
+
382
+ if (!retv)
383
+ inlen = 0;
384
+ else
385
+ memset(retv, 0, inlen);
386
+
387
+ lxc_list_for_each(it, &c->populate_devs) {
388
+ struct lxc_populate_devs *elem = it->elem;
389
+ strprint(retv, inlen, "lxc.populate.device = %s:%s:%d:%d:%o:%u:%u\n",
390
+ elem->name, elem->type, elem->maj,
391
+ elem->min, elem->file_mode, elem->uid, elem->gid);
392
+ }
393
+
394
+ return fulllen;
395
+}
396
+
397
+/* isulad: clr config populate devices*/
398
+static inline int clr_config_populate_device(const char *key, struct lxc_conf *c,
399
+ void *data)
400
+{
401
+ return lxc_clear_populate_devices(c);
402
+}
403
+
404
+/* isulad: set config for umask */
405
+static int set_config_umask(const char *key, const char *value,
406
+ struct lxc_conf *lxc_conf, void *data)
407
+{
408
+ if (lxc_config_value_empty(value)) {
409
+ ERROR("Empty umask");
410
+ return -1;
411
+ }
412
+
413
+ if (strcmp(value, "normal") == 0) {
414
+ lxc_conf->umask = 0022;
415
+ return 0;
416
+ } else if (strcmp(value, "secure") == 0) {
417
+ lxc_conf->umask = 0027;
418
+ return 0;
419
+ } else {
420
+ ERROR("Invalid native umask: %s", value);
421
+ return -1;
422
+ }
423
+}
424
+
425
+/* isulad add: get umask value*/
426
+static int get_config_umask(const char *key, char *retv, int inlen,
427
+ struct lxc_conf *c, void *data)
428
+{
429
+ return lxc_get_conf_size_t(c, retv, inlen, c->umask);
430
+}
431
+
432
+/* isulad add: clear umask value */
433
+static inline int clr_config_umask(const char *key, struct lxc_conf *c,
434
+ void *data)
435
+{
436
+ c->umask = 0027;
437
+ return 0;
438
+}
439
+
440
+/* isulad: set config for rootfs masked paths */
441
+static int set_config_rootfs_masked_paths(const char *key, const char *value,
442
+ struct lxc_conf *lxc_conf, void *data)
443
+{
444
+ struct lxc_list *list_item = NULL;
445
+
446
+ if (lxc_config_value_empty(value))
447
+ return lxc_clear_rootfs_masked_paths(lxc_conf);
448
+
449
+ list_item = malloc(sizeof(*list_item));
450
+ if (list_item == NULL)
451
+ goto on_error;
452
+
453
+ list_item->elem = safe_strdup(value);
454
+
455
+ lxc_list_add_tail(&lxc_conf->rootfs.maskedpaths, list_item);
456
+
457
+ return 0;
458
+
459
+on_error:
460
+ free(list_item);
461
+
462
+ return -1;
463
+}
464
+
465
+// isulad: get config rootfs masked paths
466
+static int get_config_rootfs_masked_paths(const char *key, char *retv, int inlen,
467
+ struct lxc_conf *c, void *data)
468
+{
469
+ int len, fulllen = 0;
470
+ struct lxc_list *it = NULL;
471
+
472
+ if (!retv)
473
+ inlen = 0;
474
+ else
475
+ memset(retv, 0, inlen);
476
+
477
+ lxc_list_for_each(it, &c->rootfs.maskedpaths) {
478
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
479
+ }
480
+
481
+ return fulllen;
482
+}
483
+
484
+/* isulad: set config for rootfs ro paths */
485
+static int set_config_rootfs_ro_paths(const char *key, const char *value,
486
+ struct lxc_conf *lxc_conf, void *data)
487
+{
488
+ struct lxc_list *list_item = NULL;
489
+
490
+ if (lxc_config_value_empty(value))
491
+ return lxc_clear_rootfs_ro_paths(lxc_conf);
492
+
493
+ list_item = malloc(sizeof(*list_item));
494
+ if (list_item == NULL)
495
+ goto on_error;
496
+
497
+ list_item->elem = safe_strdup(value);
498
+
499
+ lxc_list_add_tail(&lxc_conf->rootfs.ropaths, list_item);
500
+
501
+ return 0;
502
+
503
+on_error:
504
+ free(list_item);
505
+
506
+ return -1;
507
+}
508
+
509
+// isulad: get config rootfs ro paths
510
+static int get_config_rootfs_ro_paths(const char *key, char *retv, int inlen,
511
+ struct lxc_conf *c, void *data)
512
+{
513
+ int len, fulllen = 0;
514
+ struct lxc_list *it = NULL;
515
+
516
+ if (!retv)
517
+ inlen = 0;
518
+ else
519
+ memset(retv, 0, inlen);
520
+
521
+ lxc_list_for_each(it, &c->rootfs.ropaths) {
522
+ strprint(retv, inlen, "%s\n", (char *)it->elem);
523
+ }
524
+
525
+ return fulllen;
526
+}
527
+
528
+/* isulad: clr config rootfs masked paths */
529
+static inline int clr_config_rootfs_masked_paths(const char *key, struct lxc_conf *c,
530
+ void *data)
531
+{
532
+ return lxc_clear_rootfs_masked_paths(c);
533
+}
534
+
535
+/* isulad: clr config rootfs ro paths */
536
+static inline int clr_config_rootfs_ro_paths(const char *key, struct lxc_conf *c,
537
+ void *data)
538
+{
539
+ return lxc_clear_rootfs_ro_paths(c);
540
+}
541
+
542
+/* isulad: set config for systemd */
543
+static int set_config_systemd(const char *key, const char *value,
544
+ struct lxc_conf *lxc_conf, void *data)
545
+{
546
+ if (lxc_config_value_empty(value)) {
547
+ ERROR("Empty umask");
548
+ return -1;
549
+ }
550
+ lxc_conf->systemd = strdup(value);
551
+ return 0;
552
+}
553
+
554
+/* isulad add: get systemd value*/
555
+static int get_config_systemd(const char *key, char *retv, int inlen,
556
+ struct lxc_conf *c, void *data)
557
+{
558
+ return lxc_get_conf_str(retv, inlen, c->systemd);
559
+}
560
+
561
+/* isulad add: clear systemd value */
562
+static inline int clr_config_systemd(const char *key, struct lxc_conf *c,
563
+ void *data)
564
+{
565
+ free(c->systemd);
566
+ c->systemd = NULL;
567
+ return 0;
568
+}
569
+
570
+static int set_config_console_log_driver(const char *key, const char *value,
571
+ struct lxc_conf *lxc_conf, void *data)
572
+{
573
+ return set_config_string_item(&lxc_conf->console.log_driver, value);
574
+}
575
+
576
+static int set_config_console_syslog_tag(const char *key, const char *value,
577
+ struct lxc_conf *lxc_conf, void *data)
578
+{
579
+ if (value == NULL) {
580
+ return -1;
581
+ }
582
+ return set_config_string_item(&lxc_conf->console.log_syslog_tag, value);
583
+}
584
+
585
+static int parse_facility(const char *facility)
586
+{
587
+#define FACILITIES_LEN 20
588
+ const char *facility_keys[FACILITIES_LEN] = {
589
+ "kern", "user", "mail", "daemon", "auth",
590
+ "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp",
591
+ "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"
592
+ };
593
+ const int facilities[FACILITIES_LEN] = {
594
+ LOG_KERN, LOG_USER, LOG_MAIL, LOG_DAEMON, LOG_AUTH, LOG_SYSLOG,
595
+ LOG_LPR, LOG_NEWS, LOG_UUCP, LOG_CRON, LOG_AUTHPRIV, LOG_FTP,
596
+ LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4,
597
+ LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7
598
+ };
599
+ int i = 0;
600
+
601
+ if (facility == NULL) {
602
+ return -1;
603
+ }
604
+
605
+ for (; i < FACILITIES_LEN; i++) {
606
+ if (strcmp(facility, facility_keys[i]) == 0) {
607
+ return facilities[i];
608
+ }
609
+ }
610
+
611
+ return -1;
612
+}
613
+
614
+static int set_config_console_syslog_facility(const char *key, const char *value,
615
+ struct lxc_conf *lxc_conf, void *data)
616
+{
617
+ int facility;
618
+
619
+ facility = parse_facility(value);
620
+ if (facility < 0) {
621
+ NOTICE("Invalid facility: %s", value);
622
+ facility = LOG_DAEMON;
623
+ }
624
+
625
+ lxc_conf->console.log_syslog_facility = facility;
626
+ return 0;
627
+}
628
+
629
+static int set_config_selinux_mount_context(const char *key, const char *value,
630
+ struct lxc_conf *lxc_conf, void *data)
631
+{
632
+ if (value != NULL && strcmp(value, "unconfined_t") == 0) {
633
+ return set_config_string_item(&lxc_conf->lsm_se_mount_context, NULL);
634
+ }
635
+
636
+ return set_config_string_item(&lxc_conf->lsm_se_mount_context, value);
637
+}
638
+
639
+static int get_config_console_log_driver(const char *key, char *retv, int inlen,
640
+ struct lxc_conf *c, void *data)
641
+{
642
+ return lxc_get_conf_str(retv, inlen, c->console.log_driver);
643
+}
644
+
645
+static int get_config_console_syslog_tag(const char *key, char *retv, int inlen,
646
+ struct lxc_conf *c, void *data)
647
+{
648
+ return lxc_get_conf_str(retv, inlen, c->console.log_syslog_tag);
649
+}
650
+
651
+static int get_config_console_syslog_facility(const char *key, char *retv, int inlen,
652
+ struct lxc_conf *c, void *data)
653
+{
654
+ return lxc_get_conf_int(c, retv, inlen, c->console.log_syslog_facility);
655
+}
656
+
657
+static int get_config_selinux_mount_context(const char *key, char *retv, int inlen,
658
+ struct lxc_conf *c, void *data)
659
+{
660
+ return lxc_get_conf_str(retv, inlen, c->lsm_se_mount_context);
661
+}
662
+
663
+static inline int clr_config_console_log_driver(const char *key,
664
+ struct lxc_conf *c, void *data)
665
+{
666
+ free(c->console.log_driver);
667
+ c->console.log_driver = NULL;
668
+ return 0;
669
+}
670
+
671
+static inline int clr_config_console_syslog_tag(const char *key,
672
+ struct lxc_conf *c, void *data)
673
+{
674
+ free(c->console.log_syslog_tag);
675
+ c->console.log_syslog_tag= NULL;
676
+ return 0;
677
+}
678
+
679
+static inline int clr_config_console_syslog_facility(const char *key,
680
+ struct lxc_conf *c, void *data)
681
+{
682
+ c->console.log_syslog_facility = LOG_DAEMON;
683
+ return 0;
684
+}
685
+
686
+static inline int clr_config_selinux_mount_context(const char *key,
687
+ struct lxc_conf *c, void *data)
688
+{
689
+ free(c->lsm_se_mount_context);
690
+ c->lsm_se_mount_context = NULL;
691
+ return 0;
692
+}
693
+#endif
694
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
695
index 8df6059..d4495f7 100644
696
--- a/src/lxc/lxccontainer.c
697
+++ b/src/lxc/lxccontainer.c
698
699
#include "utils.h"
700
#include "version.h"
701
702
+#ifdef HAVE_ISULAD
703
+#include "exec_commands.h"
704
+#endif
705
+
706
#if HAVE_OPENSSL
707
#include <openssl/evp.h>
708
#endif
709
710
711
lxc_log_define(lxccontainer, lxc);
712
713
+#ifdef HAVE_ISULAD
714
+typedef bool (*func_is_io_stat_read)(const char *value);
715
+typedef bool (*func_is_io_stat_write)(const char *value);
716
+#endif
717
+
718
static bool do_lxcapi_destroy(struct lxc_container *c);
719
static const char *lxcapi_get_config_path(struct lxc_container *c);
720
#define do_lxcapi_get_config_path(c) lxcapi_get_config_path(c)
721
722
free(c->config_path);
723
c->config_path = NULL;
724
725
+#ifdef HAVE_ISULAD
726
+ free(c->exit_fifo);
727
+ c->exit_fifo = NULL;
728
+ free(c->ocihookfile);
729
+ c->ocihookfile = NULL;
730
+#endif
731
+
732
free(c);
733
}
734
735
736
return true;
737
}
738
739
+#ifdef HAVE_ISULAD
740
+static bool load_ocihooks_locked(struct lxc_container *c)
741
+{
742
+ parser_error err = NULL;
743
+ oci_runtime_spec_hooks *hooks = NULL;
744
+
745
+ if (!c->lxc_conf)
746
+ c->lxc_conf = lxc_conf_init();
747
+
748
+ if (!c->lxc_conf)
749
+ return false;
750
+
751
+ hooks = oci_runtime_spec_hooks_parse_file(c->ocihookfile, NULL, &err);
752
+ if (!hooks) {
753
+ fprintf(stderr, "parse oci hooks config failed: %s\n", err);
754
+ free(err);
755
+ return true;
756
+ }
757
+ c->lxc_conf->ocihooks = hooks;
758
+
759
+ if (err)
760
+ free(err);
761
+ return true;
762
+}
763
+
764
+/*
765
+ * isulad: set oci hook file path
766
+ * */
767
+static bool set_oci_hook_config_filename(struct lxc_container *c)
768
+{
769
+#define OCI_HOOK_JSON_FILE_NAME "ocihooks.json"
770
+ char *newpath = NULL;
771
+ int len, ret;
772
+
773
+ if (!c->config_path)
774
+ return false;
775
+
776
+ /* $lxc_path + "/" + c->name + "/" + "config" + '\0' */
777
+ if (strlen(c->config_path) + strlen(c->name) > SIZE_MAX - strlen(OCI_HOOK_JSON_FILE_NAME) - 3)
778
+ return false;
779
+ len = strlen(c->config_path) + strlen(c->name) + strlen(OCI_HOOK_JSON_FILE_NAME) + 3;
780
+
781
+ newpath = malloc(len);
782
+ if (newpath == NULL)
783
+ return false;
784
+
785
+ ret = snprintf(newpath, len, "%s/%s/%s", c->config_path, c->name, OCI_HOOK_JSON_FILE_NAME);
786
+ if (ret < 0 || ret >= len) {
787
+ fprintf(stderr, "Error printing out config file name\n");
788
+ free(newpath);
789
+ return false;
790
+ }
791
+
792
+ free(c->ocihookfile);
793
+ c->ocihookfile = newpath;
794
+
795
+ return true;
796
+}
797
+#endif
798
+
799
static bool do_lxcapi_load_config(struct lxc_container *c, const char *alt_file)
800
{
801
int lret;
802
803
804
ret = load_config_locked(c, fname);
805
806
+#ifdef HAVE_ISULAD
807
+ if (ret && file_exists(c->ocihookfile))
808
+ ret = load_ocihooks_locked(c);
809
+#endif
810
+
811
if (need_disklock)
812
container_disk_unlock(c);
813
else
814
815
return true;
816
}
817
818
+#ifdef HAVE_ISULAD
819
+/* isulad: use init argv as init cmd */
820
+static char **use_init_args(char **init_argv, size_t init_args)
821
+{
822
+ size_t i;
823
+ int nargs = 0;
824
+ char **argv;
825
+
826
+ if (!init_argv)
827
+ return NULL;
828
+
829
+ do {
830
+ argv = malloc(sizeof(char *));
831
+ } while (!argv);
832
+
833
+ argv[0] = NULL;
834
+ for (i = 0; i < init_args; i++)
835
+ push_arg(&argv, init_argv[i], &nargs);
836
+
837
+ if (nargs == 0) {
838
+ free(argv);
839
+ return NULL;
840
+ }
841
+ return argv;
842
+}
843
+#endif
844
+
845
static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
846
{
847
int ret;
848
849
NULL,
850
};
851
char **init_cmd = NULL;
852
+#ifdef HAVE_ISULAD
853
+ int keepfds[] = {-1, -1, -1, -1, -1};
854
+ ssize_t size_read;
855
+ char errbuf[BUFSIZ + 1] = {0};
856
+#endif
857
858
/* container does exist */
859
if (!c)
860
861
argv = init_cmd = split_init_cmd(conf->init_cmd);
862
}
863
864
+#ifdef HAVE_ISULAD
865
+ if (!argv) {
866
+ argv = init_cmd = use_init_args(conf->init_argv, conf->init_argc);
867
+ }
868
+
869
+ // do not allow using default rootfs path when isulad
870
+ if (conf->rootfs.mount == NULL) {
871
+ ERROR("Empty rootfs path detected");
872
+ lxc_put_handler(handler);
873
+ return false;
874
+ }
875
+
876
+ // do not allow using default args when isulad
877
+ if (!argv) {
878
+ ERROR("Empty args detected");
879
+ lxc_put_handler(handler);
880
+ return false;
881
+ }
882
+
883
+ if (c->image_type_oci) {
884
+ handler->image_type_oci = true;
885
+ }
886
+#endif
887
+
888
/* ... otherwise use default_args. */
889
if (!argv) {
890
if (useinit) {
891
892
char title[2048];
893
pid_t pid_first, pid_second;
894
895
+#ifdef HAVE_ISULAD
896
+ //isulad: pipdfd for get error message of child or grandchild process.
897
+ if (pipe2(conf->errpipe, O_CLOEXEC) != 0) {
898
+ SYSERROR("Failed to init errpipe");
899
+ free_init_cmd(init_cmd);
900
+ lxc_put_handler(handler);
901
+ return false;
902
+ }
903
+#endif
904
+
905
pid_first = fork();
906
if (pid_first < 0) {
907
free_init_cmd(init_cmd);
908
lxc_put_handler(handler);
909
+#ifdef HAVE_ISULAD
910
+ lxc_close_error_pipe(conf->errpipe);
911
+#endif
912
return false;
913
}
914
915
916
* the PID file, child will do the free and unlink.
917
*/
918
c->pidfile = NULL;
919
+#ifdef HAVE_ISULAD
920
+ close(conf->errpipe[1]);
921
+ conf->errpipe[1] = -1;
922
+#endif
923
924
/* Wait for container to tell us whether it started
925
* successfully.
926
*/
927
started = wait_on_daemonized_start(handler, pid_first);
928
+#ifdef HAVE_ISULAD
929
+ if (!started) {
930
+ size_read = read(conf->errpipe[0], errbuf, BUFSIZ);
931
+ if (size_read > 0) {
932
+ conf->errmsg = safe_strdup(errbuf);
933
+ }
934
+ }
935
+ close(conf->errpipe[0]);
936
+ conf->errpipe[0] = -1;
937
+#endif
938
939
free_init_cmd(init_cmd);
940
lxc_put_handler(handler);
941
942
if (pid_second != 0) {
943
free_init_cmd(init_cmd);
944
lxc_put_handler(handler);
945
+#ifdef HAVE_ISULAD
946
+ lxc_close_error_pipe(conf->errpipe);
947
+#endif
948
_exit(EXIT_SUCCESS);
949
}
950
951
952
_exit(EXIT_FAILURE);
953
}
954
955
+#ifdef HAVE_ISULAD
956
+ keepfds[0] = handler->conf->maincmd_fd;
957
+ keepfds[1] = handler->state_socket_pair[0];
958
+ keepfds[2] = handler->state_socket_pair[1];
959
+ keepfds[4] = conf->errpipe[1];
960
+ close(conf->errpipe[0]);
961
+ conf->errpipe[0] = -1;
962
+ ret = lxc_check_inherited(conf, true, keepfds,
963
+ sizeof(keepfds) / sizeof(keepfds[0]));
964
+#else
965
ret = inherit_fds(handler, true);
966
+#endif
967
if (ret < 0)
968
_exit(EXIT_FAILURE);
969
970
971
if (w < 0) {
972
free_init_cmd(init_cmd);
973
lxc_put_handler(handler);
974
+#ifdef HAVE_ISULAD
975
+ lxc_close_error_pipe(conf->errpipe);
976
+#endif
977
978
SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
979
980
981
if (ret < 0) {
982
free_init_cmd(init_cmd);
983
lxc_put_handler(handler);
984
+#ifdef HAVE_ISULAD
985
+ lxc_close_error_pipe(conf->errpipe);
986
+#endif
987
988
SYSERROR("Failed to write monitor pid to \"%s\"", c->pidfile);
989
990
991
}
992
}
993
994
+#ifdef HAVE_ISULAD
995
+ /* isulad: open exit fifo */
996
+ if (c->exit_fifo) {
997
+ conf->exit_fd = lxc_open(c->exit_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0);
998
+ if (conf->exit_fd < 0) {
999
+ ERROR("Failed to open exit fifo %s: %s.", c->exit_fifo, strerror(errno));
1000
+ lxc_put_handler(handler);
1001
+ ret = 1;
1002
+ goto on_error;
1003
+ }
1004
+ }
1005
+#endif
1006
+
1007
conf->reboot = REBOOT_NONE;
1008
1009
/* Unshare the mount namespace if requested */
1010
1011
}
1012
}
1013
1014
+#ifdef HAVE_ISULAD
1015
+ keepfds[0] = handler->conf->maincmd_fd;
1016
+ keepfds[1] = handler->state_socket_pair[0];
1017
+ keepfds[2] = handler->state_socket_pair[1];
1018
+
1019
+ /* keep exit fifo fd */
1020
+ if (conf->exit_fd >= 0) {
1021
+ keepfds[3] = conf->exit_fd;
1022
+ }
1023
+ /* isulad: keep errpipe fd */
1024
+ if (c->daemonize)
1025
+ keepfds[4] = conf->errpipe[1];
1026
+
1027
+ ret = lxc_check_inherited(conf, c->daemonize, keepfds,
1028
+ sizeof(keepfds) / sizeof(keepfds[0]));
1029
+ if (ret < 0) {
1030
+ lxc_put_handler(handler);
1031
+ ret = 1;
1032
+ goto on_error;
1033
+ }
1034
+#else
1035
ret = inherit_fds(handler, c->daemonize);
1036
if (ret < 0) {
1037
lxc_put_handler(handler);
1038
ret = 1;
1039
goto on_error;
1040
}
1041
+#endif
1042
1043
+#ifndef HAVE_ISULAD
1044
if (useinit)
1045
ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
1046
c->daemonize, &c->error_num);
1047
else
1048
ret = lxc_start(argv, handler, c->config_path, c->daemonize,
1049
&c->error_num);
1050
+#else
1051
+ if (useinit) {
1052
+ ret = lxc_execute(c->name, argv, 1, handler, c->config_path,
1053
+ c->daemonize, &c->error_num, c->start_timeout);
1054
+ } else {
1055
+ handler->disable_pty = c->disable_pty;
1056
+ handler->open_stdin = c->open_stdin;
1057
+ ret = lxc_start(argv, handler, c->config_path, c->daemonize,
1058
+ &c->error_num, c->start_timeout);
1059
+ }
1060
+#endif
1061
1062
if (conf->reboot == REBOOT_REQ) {
1063
INFO("Container requested reboot");
1064
1065
static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
1066
{
1067
__do_close int pidfd = -EBADF, state_client_fd = -EBADF;
1068
+#ifdef HAVE_ISULAD
1069
+ // isulad: keep default signal the same as docker
1070
+ int haltsignal = SIGTERM;
1071
+#else
1072
int haltsignal = SIGPWR;
1073
+#endif
1074
pid_t pid = -1;
1075
lxc_state_t states[MAX_STATE] = {0};
1076
int killret, ret;
1077
1078
/* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
1079
if (c->lxc_conf && c->lxc_conf->haltsignal)
1080
haltsignal = c->lxc_conf->haltsignal;
1081
+#ifndef HAVE_ISULAD
1082
else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
1083
haltsignal = (SIGRTMIN + 3);
1084
-
1085
+#endif
1086
1087
/*
1088
* Add a new state client before sending the shutdown signal so
1089
1090
return unlink(arg);
1091
}
1092
1093
+#ifdef HAVE_ISULAD
1094
+static void container_sock_dir_delete(const char *name)
1095
+{
1096
+ __do_free char *sock_dir = NULL;
1097
+
1098
+ sock_dir = generate_named_unix_sock_dir(name);
1099
+ if (sock_dir == NULL) {
1100
+ ERROR("Failed to generate exec unix sock dir");
1101
+ return;
1102
+ }
1103
+
1104
+ (void)lxc_rmdir_onedev(sock_dir, NULL);
1105
+}
1106
+#endif
1107
+
1108
static bool container_destroy(struct lxc_container *c,
1109
struct lxc_storage *storage)
1110
{
1111
1112
bool bret = false;
1113
int ret = 0;
1114
1115
+#ifdef HAVE_ISULAD
1116
+ if (!c)
1117
+ return false;
1118
+ // isulad: if container is not defined, we need to remove disk lock file
1119
+ // which is created in lxc_container_new.
1120
+ if (!do_lxcapi_is_defined(c)) {
1121
+ container_disk_removelock(c);
1122
+ return false;
1123
+ }
1124
+#else
1125
if (!c || !do_lxcapi_is_defined(c))
1126
return false;
1127
+#endif
1128
1129
conf = c->lxc_conf;
1130
if (container_disk_lock(c))
1131
1132
if (ret < 0) {
1133
ERROR("Failed to destroy directory \"%s\" for \"%s\"", path,
1134
c->name);
1135
+#ifdef HAVE_ISULAD
1136
+ char msg[BUFSIZ] = { 0 };
1137
+ ret = snprintf(msg, BUFSIZ, "Failed to destroy directory \"%s\": %s", path, errno ? strerror(errno) : "error");
1138
+ if (ret < 0 || ret >= BUFSIZ) {
1139
+ ERROR("Sprintf failed");
1140
+ goto out;
1141
+ }
1142
+ c->error_string = safe_strdup(msg);
1143
+#endif
1144
goto out;
1145
}
1146
+#ifdef HAVE_ISULAD
1147
+ container_sock_dir_delete(c->name);
1148
+#endif
1149
INFO("Destroyed directory \"%s\" for \"%s\"", path, c->name);
1150
1151
on_success:
1152
1153
free(path);
1154
1155
container_disk_unlock(c);
1156
+#ifdef HAVE_ISULAD
1157
+ if (bret && container_disk_removelock(c)) {
1158
+ bret = false;
1159
+ }
1160
+#endif
1161
return bret;
1162
}
1163
1164
1165
1166
current_config = c->lxc_conf;
1167
1168
+#ifdef HAVE_ISULAD
1169
+ ret = lxc_attach(c, exec_function, exec_payload, options,
1170
+ attached_process, &c->lxc_conf->errmsg);
1171
+#else
1172
ret = lxc_attach(c, exec_function, exec_payload, options,
1173
attached_process);
1174
+#endif
1175
current_config = NULL;
1176
return ret;
1177
}
1178
1179
command.program = (char *)program;
1180
command.argv = (char **)argv;
1181
1182
+#ifdef HAVE_ISULAD
1183
+ ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid, NULL);
1184
+#else
1185
ret = lxc_attach(c, lxc_attach_run_command, &command, options, &pid);
1186
+#endif
1187
if (ret < 0)
1188
return ret;
1189
1190
1191
1192
WRAP_API(int, lxcapi_seccomp_notify_fd_active)
1193
1194
+#ifdef HAVE_ISULAD
1195
+/* isulad add set console fifos*/
1196
+static bool do_lxcapi_set_terminal_default_fifos(struct lxc_container *c, const char *in, const char *out, const char *err)
1197
+{
1198
+ struct lxc_conf *conf = NULL;
1199
+
1200
+ if (!c || !c->lxc_conf)
1201
+ return false;
1202
+ if (container_mem_lock(c)) {
1203
+ ERROR("Error getting mem lock");
1204
+ return false;
1205
+ }
1206
+
1207
+ conf = c->lxc_conf;
1208
+ if (in) {
1209
+ if (conf->console.init_fifo[0])
1210
+ free(conf->console.init_fifo[0]);
1211
+ conf->console.init_fifo[0] = safe_strdup(in);
1212
+ }
1213
+ if (out) {
1214
+ if (conf->console.init_fifo[1])
1215
+ free(conf->console.init_fifo[1]);
1216
+ conf->console.init_fifo[1] = safe_strdup(out);
1217
+ }
1218
+ if (err) {
1219
+ if (conf->console.init_fifo[2])
1220
+ free(conf->console.init_fifo[2]);
1221
+ conf->console.init_fifo[2] = safe_strdup(err);
1222
+ }
1223
+
1224
+ container_mem_unlock(c);
1225
+ return true;
1226
+}
1227
+
1228
+WRAP_API_3(bool, lxcapi_set_terminal_default_fifos, const char *, const char *, const char *)
1229
+
1230
+/* isulad add set info file path */
1231
+static bool do_lxcapi_set_container_info_file(struct lxc_container *c, const char *info_file)
1232
+{
1233
+ struct lxc_conf *conf = NULL;
1234
+
1235
+ if (!c || !c->lxc_conf || !info_file)
1236
+ return false;
1237
+ if (container_mem_lock(c)) {
1238
+ ERROR("Error getting mem lock");
1239
+ return false;
1240
+ }
1241
+
1242
+ conf = c->lxc_conf;
1243
+ if (conf->container_info_file)
1244
+ free(conf->container_info_file);
1245
+ conf->container_info_file = safe_strdup(info_file);
1246
+
1247
+ container_mem_unlock(c);
1248
+ return true;
1249
+}
1250
+
1251
+WRAP_API_1(bool, lxcapi_set_container_info_file, const char *)
1252
+
1253
+static bool do_lxcapi_want_disable_pty(struct lxc_container *c, bool state)
1254
+{
1255
+ if (!c || !c->lxc_conf)
1256
+ return false;
1257
+
1258
+ if (container_mem_lock(c))
1259
+ return false;
1260
+
1261
+ c->disable_pty = state;
1262
+
1263
+ container_mem_unlock(c);
1264
+
1265
+ return true;
1266
+}
1267
+
1268
+WRAP_API_1(bool, lxcapi_want_disable_pty, bool)
1269
+
1270
+static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state)
1271
+{
1272
+ if (!c || !c->lxc_conf)
1273
+ return false;
1274
+
1275
+ if (container_mem_lock(c))
1276
+ return false;
1277
+
1278
+ c->open_stdin = state;
1279
+
1280
+ container_mem_unlock(c);
1281
+
1282
+ return true;
1283
+}
1284
+
1285
+WRAP_API_1(bool, lxcapi_want_open_stdin, bool)
1286
+
1287
+/* isulad add clean resources */
1288
+static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo)
1289
+{
1290
+ bool ret = true;
1291
+
1292
+ if (!c || !c->lxc_conf)
1293
+ return false;
1294
+ if (container_mem_lock(c)) {
1295
+ ERROR("Error getting mem lock");
1296
+ return false;
1297
+ }
1298
+
1299
+ if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo, err_fifo)) {
1300
+ ERROR("Error set console fifos");
1301
+ ret = false;
1302
+ }
1303
+
1304
+ container_mem_unlock(c);
1305
+ return ret;
1306
+}
1307
+
1308
+WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *)
1309
+
1310
+static bool do_lxcapi_set_terminal_winch(struct lxc_container *c, unsigned int height, unsigned int width)
1311
+{
1312
+ bool ret = true;
1313
+
1314
+ if (!c || !c->lxc_conf)
1315
+ return false;
1316
+ if (container_mem_lock(c)) {
1317
+ ERROR("Error getting mem lock");
1318
+ return false;
1319
+ }
1320
+
1321
+ if (lxc_cmd_set_terminal_winch(c->name, c->config_path, height, width)) {
1322
+ ERROR("Error set terminal winch");
1323
+ ret = false;
1324
+ }
1325
+
1326
+ container_mem_unlock(c);
1327
+ return ret;
1328
+}
1329
+
1330
+WRAP_API_2(bool, lxcapi_set_terminal_winch, unsigned int, unsigned int)
1331
+
1332
+static bool do_lxcapi_set_exec_terminal_winch(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width)
1333
+{
1334
+ bool ret = true;
1335
+
1336
+ if (!c || !c->lxc_conf)
1337
+ return false;
1338
+ if (container_mem_lock(c)) {
1339
+ ERROR("Error getting mem lock");
1340
+ return false;
1341
+ }
1342
+
1343
+ if (lxc_exec_cmd_set_terminal_winch(c->name, c->config_path, suffix, height, width)) {
1344
+ ERROR("Error set terminal winch");
1345
+ ret = false;
1346
+ }
1347
+
1348
+ container_mem_unlock(c);
1349
+ return ret;
1350
+}
1351
+
1352
+WRAP_API_3(bool, lxcapi_set_exec_terminal_winch, const char *, unsigned int, unsigned int)
1353
+
1354
+/* isulad add clean resources */
1355
+static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pid)
1356
+{
1357
+ int ret;
1358
+
1359
+ if (!c)
1360
+ return false;
1361
+
1362
+ ret = do_lxcapi_clean_resource(c->name, c->config_path, c->lxc_conf, pid);
1363
+ if (ret)
1364
+ ERROR("Failed to clean container %s resource", c->name);
1365
+ return ret == 0;
1366
+
1367
+}
1368
+
1369
+WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t)
1370
+
1371
+/* isulad get coantainer pids */
1372
+static bool do_lxcapi_get_container_pids(struct lxc_container *c, pid_t **pids,size_t *pids_len)
1373
+{
1374
+ int ret;
1375
+
1376
+ if (!c)
1377
+ return false;
1378
+
1379
+ ret = do_lxcapi_get_pids(c->name, c->config_path, c->lxc_conf, pids,pids_len);
1380
+ if (ret)
1381
+ ERROR("Failed to get container %s pids", c->name);
1382
+ return ret == 0;
1383
+
1384
+}
1385
+
1386
+WRAP_API_2(bool, lxcapi_get_container_pids, pid_t **,size_t *)
1387
+
1388
+/* isulad add start timeout */
1389
+static bool do_lxcapi_set_start_timeout(struct lxc_container *c, unsigned int start_timeout)
1390
+{
1391
+ if (!c || !c->lxc_conf)
1392
+ return false;
1393
+ if (container_mem_lock(c)) {
1394
+ ERROR("Error getting mem lock");
1395
+ return false;
1396
+ }
1397
+ c->start_timeout = start_timeout;
1398
+ container_mem_unlock(c);
1399
+ return true;
1400
+}
1401
+
1402
+WRAP_API_1(bool, lxcapi_set_start_timeout, unsigned int)
1403
+
1404
+/* isulad add set image type */
1405
+static bool do_lxcapi_set_oci_type(struct lxc_container *c, bool image_type_oci)
1406
+{
1407
+ if (!c || !c->lxc_conf)
1408
+ return false;
1409
+ if (container_mem_lock(c)) {
1410
+ ERROR("Error getting mem lock");
1411
+ return false;
1412
+ }
1413
+ c->image_type_oci = image_type_oci;
1414
+ container_mem_unlock(c);
1415
+ return true;
1416
+}
1417
+
1418
+WRAP_API_1(bool, lxcapi_set_oci_type, bool)
1419
+
1420
+static uint64_t metrics_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
1421
+{
1422
+ char buf[81] = {0};
1423
+ int len = 0;
1424
+ uint64_t val = 0;
1425
+
1426
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1427
+ if (len <= 0) {
1428
+ DEBUG("unable to read cgroup item %s", item);
1429
+ return 0;
1430
+ }
1431
+
1432
+ val = strtoull(buf, NULL, 0);
1433
+ return val;
1434
+}
1435
+
1436
+static uint64_t metrics_get_ull_with_max(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item)
1437
+{
1438
+ char buf[81] = {0};
1439
+ int len = 0;
1440
+ uint64_t val = 0;
1441
+
1442
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1443
+ if (len <= 0) {
1444
+ DEBUG("unable to read cgroup item %s", item);
1445
+ return 0;
1446
+ }
1447
+
1448
+ if (strcmp(buf, "max") == 0) {
1449
+ return ULONG_MAX;
1450
+ }
1451
+
1452
+ val = strtoull(buf, NULL, 0);
1453
+ return val;
1454
+}
1455
+
1456
+static inline bool is_blk_metrics_read(const char *value)
1457
+{
1458
+ return strcmp(value, "Read") == 0;
1459
+}
1460
+
1461
+static inline bool is_blk_metrics_write(const char *value)
1462
+{
1463
+ return strcmp(value, "Write") == 0;
1464
+}
1465
+
1466
+static inline bool is_blk_metrics_total(const char *value)
1467
+{
1468
+ return strcmp(value, "Total") == 0;
1469
+}
1470
+
1471
+static void metrics_get_blk_stats(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, struct lxc_blkio_metrics *stats)
1472
+{
1473
+ char *buf = NULL;
1474
+ int i = 0;
1475
+ int len = 0;
1476
+ int ret = 0;
1477
+ char **lines = NULL;
1478
+ char **cols = NULL;
1479
+
1480
+ len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
1481
+ if (len <= 0) {
1482
+ DEBUG("unable to read cgroup item %s", item);
1483
+ return;
1484
+ }
1485
+
1486
+ buf = malloc(len + 1);
1487
+ (void)memset(buf, 0, len + 1);
1488
+ ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
1489
+ if (ret <= 0) {
1490
+ DEBUG("unable to read cgroup item %s", item);
1491
+ goto out;
1492
+ }
1493
+
1494
+ lines = lxc_string_split_and_trim(buf, '\n');
1495
+ if (lines == NULL) {
1496
+ goto out;
1497
+ }
1498
+
1499
+ (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
1500
+
1501
+ for (i = 0; lines[i]; i++) {
1502
+ cols = lxc_string_split_and_trim(lines[i], ' ');
1503
+ if (cols == NULL) {
1504
+ goto err_out;
1505
+ }
1506
+ if (lxc_array_len((void **)cols) == 3) {
1507
+ if (is_blk_metrics_read(cols[1])) {
1508
+ stats->read += strtoull(cols[2], NULL, 0);
1509
+ } else if (is_blk_metrics_write(cols[1])) {
1510
+ stats->write += strtoull(cols[2], NULL, 0);
1511
+ }
1512
+ }
1513
+ if (lxc_array_len((void **)cols) == 2 && is_blk_metrics_total(cols[0])) {
1514
+ stats->total = strtoull(cols[1], NULL, 0);
1515
+ }
1516
+
1517
+ lxc_free_array((void **)cols, free);
1518
+ }
1519
+err_out:
1520
+ lxc_free_array((void **)lines, free);
1521
+out:
1522
+ free(buf);
1523
+ return;
1524
+}
1525
+
1526
+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)
1527
+{
1528
+ char *buf = NULL;
1529
+ int i = 0;
1530
+ int j = 0;
1531
+ int len = 0;
1532
+ int ret = 0;
1533
+ char **lines = NULL;
1534
+ char **cols = NULL;
1535
+ char **kv = NULL;
1536
+
1537
+ len = cgroup_ops->get(cgroup_ops, item, NULL, 0, c->name, c->config_path);
1538
+ if (len <= 0) {
1539
+ DEBUG("unable to read cgroup item %s", item);
1540
+ return;
1541
+ }
1542
+
1543
+ buf = malloc(len + 1);
1544
+ (void)memset(buf, 0, len + 1);
1545
+ ret = cgroup_ops->get(cgroup_ops, item, buf, len, c->name, c->config_path);
1546
+ if (ret <= 0) {
1547
+ DEBUG("unable to read cgroup item %s", item);
1548
+ goto out;
1549
+ }
1550
+
1551
+ lines = lxc_string_split_and_trim(buf, '\n');
1552
+ if (lines == NULL) {
1553
+ goto out;
1554
+ }
1555
+
1556
+ (void)memset(stats, 0, sizeof(struct lxc_blkio_metrics));
1557
+ // line example:
1558
+ // 259:0 rbytes=0 wbytes=12288 rios=0 wios=4 dbytes=0 dios=0
1559
+ for (i = 0; lines[i]; i++) {
1560
+ cols = lxc_string_split_and_trim(lines[i], ' ');
1561
+ if (cols == NULL || lxc_array_len((void **)cols) < 2) {
1562
+ goto err_out;
1563
+ }
1564
+ len = lxc_array_len((void **)cols);
1565
+ for (j = 1; j < len; j++) {
1566
+ kv = lxc_string_split(cols[j], '=');
1567
+ if (kv == NULL || lxc_array_len((void **)kv) != 2) {
1568
+ lxc_free_array((void **)kv, free);
1569
+ continue;
1570
+ }
1571
+ if (is_io_stat_read(kv[0])) {
1572
+ stats->read += strtoull(kv[1], NULL, 0);
1573
+ } else if (is_io_stat_write(kv[0])) {
1574
+ stats->write += strtoull(kv[1], NULL, 0);
1575
+ }
1576
+ lxc_free_array((void **)kv, free);
1577
+ }
1578
+ lxc_free_array((void **)cols, free);
1579
+ }
1580
+
1581
+ stats->total = stats->read + stats->write;
1582
+
1583
+err_out:
1584
+ lxc_free_array((void **)lines, free);
1585
+out:
1586
+ free(buf);
1587
+ return;
1588
+}
1589
+
1590
+static uint64_t metrics_match_get_ull(struct lxc_container *c, struct cgroup_ops *cgroup_ops, const char *item, const char *match, int column)
1591
+{
1592
+#define BUFSIZE 4096
1593
+ char buf[BUFSIZE] = {0};
1594
+ int i = 0;
1595
+ int j = 0;
1596
+ int len = 0;
1597
+ uint64_t val = 0;
1598
+ char **lines = NULL;
1599
+ char **cols = NULL;
1600
+ size_t matchlen = 0;
1601
+
1602
+ len = cgroup_ops->get(cgroup_ops, item, buf, sizeof(buf) - 1, c->name, c->config_path);
1603
+ if (len <= 0) {
1604
+ DEBUG("unable to read cgroup item %s", item);
1605
+ goto err_out;
1606
+ }
1607
+
1608
+ lines = lxc_string_split_and_trim(buf, '\n');
1609
+ if (lines == NULL) {
1610
+ goto err_out;
1611
+ }
1612
+
1613
+ matchlen = strlen(match);
1614
+ for (i = 0; lines[i]; i++) {
1615
+ if (strncmp(lines[i], match, matchlen) != 0) {
1616
+ continue;
1617
+ }
1618
+
1619
+ cols = lxc_string_split_and_trim(lines[i], ' ');
1620
+ if (cols == NULL) {
1621
+ goto err1;
1622
+ }
1623
+ for (j = 0; cols[j]; j++) {
1624
+ if (j == column) {
1625
+ val = strtoull(cols[j], NULL, 0);
1626
+ break;
1627
+ }
1628
+ }
1629
+ lxc_free_array((void **)cols, free);
1630
+ break;
1631
+ }
1632
+err1:
1633
+ lxc_free_array((void **)lines, free);
1634
+err_out:
1635
+ return val;
1636
+}
1637
+
1638
+static bool is_io_stat_rbytes(const char *value)
1639
+{
1640
+ return strcmp(value, "rbytes") == 0;
1641
+}
1642
+
1643
+static bool is_io_stat_wbytes(const char *value)
1644
+{
1645
+ return strcmp(value, "wbytes") == 0;
1646
+}
1647
+
1648
+static bool is_io_stat_rios(const char *value)
1649
+{
1650
+ return strcmp(value, "rios") == 0;
1651
+}
1652
+
1653
+static bool is_io_stat_wios(const char *value)
1654
+{
1655
+ return strcmp(value, "wios") == 0;
1656
+}
1657
+
1658
+static bool unified_metrics_get(struct lxc_container *c, struct cgroup_ops *cgroup_ops, struct lxc_container_metrics *metrics)
1659
+{
1660
+ // cpu
1661
+ metrics->cpu_use_nanos = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "usage_usec", 1) * 1000;
1662
+ metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "user_usec", 1) * 1000;
1663
+ metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpu.stat", "system_usec", 1) * 1000;
1664
+
1665
+ // io
1666
+ metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_service_bytes, is_io_stat_rbytes, is_io_stat_wbytes);
1667
+ metrics_get_io_stats_v2(c, cgroup_ops, "io.stat", &metrics->io_serviced, is_io_stat_rios, is_io_stat_wios);
1668
+
1669
+ // memory
1670
+ metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.current");
1671
+ metrics->mem_limit = metrics_get_ull_with_max(c, cgroup_ops, "memory.max");
1672
+ metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "inactive_file", 1);
1673
+ metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "file", 1);
1674
+ metrics->cache_total = metrics->cache;
1675
+
1676
+ // cgroup v2 does not support kernel memory
1677
+ metrics->kmem_used = 0;
1678
+ metrics->kmem_limit = 0;
1679
+
1680
+ // pids
1681
+ metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
1682
+
1683
+ return true;
1684
+}
1685
+
1686
+/* isulad add get container metrics */
1687
+static bool do_lxcapi_get_container_metrics(struct lxc_container *c, struct lxc_container_metrics *metrics)
1688
+{
1689
+ call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
1690
+ const char *state = NULL;
1691
+ if (c == NULL || c->lxc_conf == NULL || metrics == NULL) {
1692
+ return false;
1693
+ }
1694
+
1695
+ state = c->state(c);
1696
+ metrics->state = state;
1697
+
1698
+ if (!is_stopped(c)) {
1699
+ metrics->init = c->init_pid(c);
1700
+ } else {
1701
+ metrics->init = -1;
1702
+ }
1703
+
1704
+ cgroup_ops = cgroup_init(c->lxc_conf);
1705
+ if (cgroup_ops == NULL) {
1706
+ return false;
1707
+ }
1708
+
1709
+ if (cgroup_ops->cgroup_layout == CGROUP_LAYOUT_UNIFIED) {
1710
+ return unified_metrics_get(c, cgroup_ops, metrics);
1711
+ }
1712
+
1713
+ metrics->cpu_use_nanos = metrics_get_ull(c, cgroup_ops, "cpuacct.usage");
1714
+ metrics->pids_current = metrics_get_ull(c, cgroup_ops, "pids.current");
1715
+
1716
+ metrics->rss_bytes = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "rss", 1);
1717
+ metrics->page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgfault", 1);
1718
+ metrics->major_page_faults = metrics_match_get_ull(c,cgroup_ops, "memory.stat", "pgmajfault", 1);
1719
+
1720
+ metrics->cpu_use_user = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "user", 1);
1721
+ metrics->cpu_use_sys = metrics_match_get_ull(c, cgroup_ops, "cpuacct.stat", "system", 1);
1722
+
1723
+ // Try to read CFQ stats available on all CFQ enabled kernels first
1724
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_serviced_recursive", &metrics->io_serviced);
1725
+ if (metrics->io_serviced.read == 0 && metrics->io_serviced.write == 0 && metrics->io_serviced.total == 0) {
1726
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_service_bytes", &metrics->io_service_bytes);
1727
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.throttle.io_serviced", &metrics->io_serviced);
1728
+ } else {
1729
+ metrics_get_blk_stats(c, cgroup_ops, "blkio.io_service_bytes_recursive", &metrics->io_service_bytes);
1730
+ }
1731
+
1732
+ metrics->mem_used = metrics_get_ull(c, cgroup_ops, "memory.usage_in_bytes");
1733
+ metrics->mem_limit = metrics_get_ull(c, cgroup_ops, "memory.limit_in_bytes");
1734
+ metrics->kmem_used = metrics_get_ull(c, cgroup_ops, "memory.kmem.usage_in_bytes");
1735
+ metrics->kmem_limit = metrics_get_ull(c, cgroup_ops, "memory.kmem.limit_in_bytes");
1736
+
1737
+ metrics->cache = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "cache", 1);
1738
+ metrics->cache_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_cache", 1);
1739
+ metrics->inactive_file_total = metrics_match_get_ull(c, cgroup_ops, "memory.stat", "total_inactive_file", 1);
1740
+
1741
+ return true;
1742
+}
1743
+
1744
+WRAP_API_1(bool, lxcapi_get_container_metrics, struct lxc_container_metrics *)
1745
+
1746
+#endif
1747
+
1748
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
1749
{
1750
struct lxc_container *c;
1751
1752
goto err;
1753
}
1754
1755
+#ifdef HAVE_ISULAD
1756
+ if (!set_oci_hook_config_filename(c)) {
1757
+ fprintf(stderr, "Error allocating oci hooks file pathname\n");
1758
+ goto err;
1759
+ }
1760
+
1761
+ if (load_config && file_exists(c->configfile)) {
1762
+ if (!lxcapi_load_config(c, NULL)) {
1763
+ fprintf(stderr, "Failed to load config for %s\n", name);
1764
+ goto err;
1765
+ }
1766
+ }
1767
+#else
1768
if (file_exists(c->configfile) && !lxcapi_load_config(c, NULL)) {
1769
fprintf(stderr, "Failed to load config for %s\n", name);
1770
goto err;
1771
}
1772
+#endif
1773
1774
rc = ongoing_create(c);
1775
switch (rc) {
1776
1777
1778
c->daemonize = true;
1779
c->pidfile = NULL;
1780
+#ifdef HAVE_ISULAD
1781
+ c->image_type_oci = false;
1782
+#endif
1783
1784
/* Assign the member functions. */
1785
c->is_defined = lxcapi_is_defined;
1786
1787
c->umount = lxcapi_umount;
1788
c->seccomp_notify_fd = lxcapi_seccomp_notify_fd;
1789
c->seccomp_notify_fd_active = lxcapi_seccomp_notify_fd_active;
1790
+#ifdef HAVE_ISULAD
1791
+ c->set_container_info_file = lxcapi_set_container_info_file;
1792
+ c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
1793
+ c->add_terminal_fifos = lxcapi_add_terminal_fifo;
1794
+ c->set_terminal_winch = lxcapi_set_terminal_winch;
1795
+ c->set_exec_terminal_winch = lxcapi_set_exec_terminal_winch;
1796
+ c->want_disable_pty = lxcapi_want_disable_pty;
1797
+ c->want_open_stdin = lxcapi_want_open_stdin;
1798
+ c->clean_container_resource = lxcapi_clean_container_resource;
1799
+ c->get_container_pids = lxcapi_get_container_pids;
1800
+ c->set_start_timeout = lxcapi_set_start_timeout;
1801
+ c->set_oci_type = lxcapi_set_oci_type;
1802
+ c->get_container_metrics = lxcapi_get_container_metrics;
1803
+#endif
1804
1805
return c;
1806
1807
1808
return NULL;
1809
}
1810
1811
+#ifdef HAVE_ISULAD
1812
+// isulad: new container without load config to save time
1813
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath)
1814
+{
1815
+ return do_lxc_container_new(name, configpath, false);
1816
+}
1817
+
1818
+struct lxc_container *lxc_container_new(const char *name, const char *configpath)
1819
+{
1820
+ return do_lxc_container_new(name, configpath, true);
1821
+}
1822
+#endif
1823
+
1824
int lxc_get_wait_states(const char **states)
1825
{
1826
int i;
1827
1828
continue;
1829
}
1830
1831
+#ifdef HAVE_ISULAD
1832
+ if (ct_name && ct_name_cnt) {
1833
+ if (array_contains(&ct_name, p, ct_name_cnt)) {
1834
+ if (is_hashed)
1835
+ free(p);
1836
+ continue;
1837
+ }
1838
+ }
1839
+#else
1840
if (array_contains(&ct_name, p, ct_name_cnt)) {
1841
if (is_hashed)
1842
free(p);
1843
continue;
1844
}
1845
+#endif
1846
1847
if (!add_to_array(&ct_name, p, ct_name_cnt)) {
1848
if (is_hashed)
1849
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
1850
index 3386bff..06e8f0b 100644
1851
--- a/src/lxc/lxccontainer.h
1852
+++ b/src/lxc/lxccontainer.h
1853
1854
#define LXC_CREATE_MAXFLAGS (1 << 1) /*!< Number of \c LXC_CREATE* flags */
1855
#define LXC_MOUNT_API_V1 1
1856
1857
+#ifdef HAVE_ISULAD
1858
+#define LXC_IMAGE_OCI_KEY "lxc.imagetype.oci"
1859
+#endif
1860
+
1861
struct bdev_specs;
1862
1863
struct lxc_snapshot;
1864
1865
int version;
1866
};
1867
1868
+#ifdef HAVE_ISULAD
1869
+struct lxc_blkio_metrics {
1870
+ uint64_t read;
1871
+ uint64_t write;
1872
+ uint64_t total;
1873
+};
1874
+
1875
+struct lxc_container_metrics {
1876
+ /* State of container */
1877
+ const char *state;
1878
+ /* The process ID of the init container */
1879
+ pid_t init;
1880
+ /* Current pids */
1881
+ uint64_t pids_current;
1882
+ /* CPU usage */
1883
+ uint64_t cpu_use_nanos;
1884
+ uint64_t cpu_use_user;
1885
+ uint64_t cpu_use_sys;
1886
+ /* BlkIO usage */
1887
+ struct lxc_blkio_metrics io_service_bytes;
1888
+ struct lxc_blkio_metrics io_serviced;
1889
+ /* Memory usage */
1890
+ uint64_t mem_used;
1891
+ uint64_t mem_limit;
1892
+ uint64_t rss_bytes;
1893
+ uint64_t page_faults;
1894
+ uint64_t major_page_faults;
1895
+ /* Kernel Memory usage */
1896
+ uint64_t kmem_used;
1897
+ uint64_t kmem_limit;
1898
+ /* Cache usage */
1899
+ uint64_t cache;
1900
+ uint64_t cache_total;
1901
+ /* total inactive file */
1902
+ uint64_t inactive_file_total;
1903
+};
1904
+#endif
1905
+
1906
/*!
1907
* An LXC container.
1908
*
1909
1910
/*! Full path to configuration file */
1911
char *config_path;
1912
1913
+#ifdef HAVE_ISULAD
1914
+ /*! isulad:
1915
+ * \private
1916
+ * exit FIFO File to open used monitor the state of lxc monitor process.
1917
+ */
1918
+ char *exit_fifo;
1919
+ /*! Whether container wishes to create pty or pipes for console log */
1920
+ bool disable_pty;
1921
+
1922
+ /*! Whether container wishes to keep stdin active */
1923
+ bool open_stdin;
1924
+
1925
+ /*!
1926
+ * \private
1927
+ * isulad: support oci hook from json file
1928
+ * full path of json file
1929
+ * */
1930
+ char *ocihookfile;
1931
+
1932
+ /*! isulad:
1933
+ * \private
1934
+ * start_timeout.
1935
+ */
1936
+ unsigned int start_timeout;
1937
+
1938
+ /*! isulad:
1939
+ * \private
1940
+ * image_type_oci
1941
+ */
1942
+ bool image_type_oci;
1943
+#endif
1944
+
1945
/*!
1946
* \brief Determine if \c /var/lib/lxc/$name/config exists.
1947
*
1948
1949
* \return Mount fd of the container's devpts instance.
1950
*/
1951
int (*devpts_fd)(struct lxc_container *c);
1952
+
1953
+#ifdef HAVE_ISULAD
1954
+ /*! isulad add
1955
+ * \brief An API call to set the path of info file
1956
+ *
1957
+ * \param c Container.
1958
+ * \param info_file Value of the path of info file.
1959
+ *
1960
+ * \return \c true on success, else \c false.
1961
+ */
1962
+ bool (*set_container_info_file) (struct lxc_container *c, const char *info_file);
1963
+
1964
+ /*! isulad add
1965
+ * \brief An API call to change the path of the console default fifos
1966
+ *
1967
+ * \param c Container.
1968
+ * \param path Value of the console path.
1969
+ *
1970
+ * \return \c true on success, else \c false.
1971
+ */
1972
+ bool (*set_terminal_init_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
1973
+
1974
+ /*! isulad add
1975
+ * \brief An API call to add the path of terminal fifos
1976
+ *
1977
+ * \param c Container.
1978
+ * \param path Value of the console path..
1979
+ *
1980
+ * \return \c true on success, else \c false.
1981
+ */
1982
+ bool (*add_terminal_fifos)(struct lxc_container *c, const char *in, const char *out, const char *err);
1983
+
1984
+ bool (*set_terminal_winch)(struct lxc_container *c, unsigned int height, unsigned int width);
1985
+
1986
+ bool (*set_exec_terminal_winch)(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width);
1987
+
1988
+ /*!
1989
+ * \brief Change whether the container wants to create pty or pipes
1990
+ * from the console log.
1991
+ *
1992
+ * \param c Container.
1993
+ * \param state Value for the disable pty bit (0 or 1).
1994
+ *
1995
+ * \return \c true on success, else \c false.
1996
+ */
1997
+ bool (*want_disable_pty)(struct lxc_container *c, bool state);
1998
+
1999
+ /*!
2000
+ * \brief Change whether the container wants to keep stdin active
2001
+ * for parent process of container
2002
+ *
2003
+ * \param c Container.
2004
+ * \param state Value for the open_stdin bit (0 or 1).
2005
+ *
2006
+ * \return \c true on success, else \c false.
2007
+ */
2008
+ bool (*want_open_stdin)(struct lxc_container *c, bool state);
2009
+
2010
+ /*! isulad add
2011
+ * \brief An API call to clean resources of container
2012
+ *
2013
+ * \param c Container.
2014
+ * \param pid Value of container process.
2015
+ *
2016
+ * \return \c true on success, else \c false.
2017
+ */
2018
+ bool (*clean_container_resource) (struct lxc_container *c, pid_t pid);
2019
+
2020
+ /*! isulad add
2021
+ * \brief An API call to get container pids
2022
+ *
2023
+ * \param c Container.
2024
+ * \param pids Value of container pids.
2025
+ * \param pids_len Value of container pids len.
2026
+ * \param pid Value of container pid.
2027
+ * \return \c true on success, else \c false.
2028
+ */
2029
+ bool (*get_container_pids)(struct lxc_container *c,pid_t **pids,size_t *pids_len);
2030
+
2031
+ /*! isulad add
2032
+ * \brief An API call to set start timeout
2033
+ *
2034
+ * \param c Container.
2035
+ * \param start_timeout Value of start timeout.
2036
+ *
2037
+ * \return \c true on success, else \c false.
2038
+ */
2039
+ bool (*set_start_timeout)(struct lxc_container *c, unsigned int start_timeout);
2040
+
2041
+ /*! isulad add
2042
+ * \brief An API call to set oci type
2043
+ *
2044
+ * \param c Container.
2045
+ * \param image_type_oci image oci type.
2046
+ *
2047
+ * \return \c true on success, else \c false.
2048
+ */
2049
+ bool (*set_oci_type)(struct lxc_container *c, bool image_type_oci);
2050
+
2051
+ /*! isulad add
2052
+ * \brief An API call to set start timeout
2053
+ *
2054
+ * \param c Container.
2055
+ * \param start_timeout Value of start timeout.
2056
+ *
2057
+ * \return \c true on success, else \c false.
2058
+ */
2059
+ bool (*get_container_metrics)(struct lxc_container *c, struct lxc_container_metrics *metrics);
2060
+#endif
2061
};
2062
2063
/*!
2064
2065
*/
2066
struct lxc_container *lxc_container_new(const char *name, const char *configpath);
2067
2068
+#ifdef HAVE_ISULAD
2069
+/*!
2070
+ * \brief Create a new container without loading config.
2071
+ *
2072
+ * \param name Name to use for container.
2073
+ * \param configpath Full path to configuration file to use.
2074
+ *
2075
+ * \return Newly-allocated container, or \c NULL on error.
2076
+ *
2077
+ * \note This function can only used for listing container.
2078
+ */
2079
+struct lxc_container *lxc_container_without_config_new(const char *name, const char *configpath);
2080
+#endif
2081
+
2082
/*!
2083
* \brief Add a reference to the specified container.
2084
*
2085
diff --git a/src/lxc/start.c b/src/lxc/start.c
2086
index 9f68304..70af128 100644
2087
--- a/src/lxc/start.c
2088
+++ b/src/lxc/start.c
2089
2090
{
2091
int ret;
2092
sigset_t mask;
2093
+#ifdef HAVE_ISULAD
2094
+ const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH, SIGTERM};
2095
+#else
2096
const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH};
2097
+#endif
2098
2099
/* Block everything except serious error signals. */
2100
ret = sigfillset(&mask);
2101
2102
2103
TRACE("Mainloop is ready");
2104
2105
+#ifdef HAVE_ISULAD
2106
+ // iSulad: close stdin pipe if we do not want open_stdin with container stdin
2107
+ if (!handler->conf->console.open_stdin) {
2108
+ if (handler->conf->console.pipes[0][1] > 0) {
2109
+ close(handler->conf->console.pipes[0][1]);
2110
+ handler->conf->console.pipes[0][1] = -1;
2111
+ }
2112
+ }
2113
+#endif
2114
+
2115
ret = lxc_mainloop(&descr, -1);
2116
if (descr.type == LXC_MAINLOOP_EPOLL)
2117
close_prot_errno_disarm(descr.epfd);
2118
2119
if (console) {
2120
ret = lxc_terminal_mainloop_add(&descr_console, console);
2121
if (ret == 0)
2122
+#ifdef HAVE_ISULAD
2123
+ ret = isulad_safe_mainloop(&descr_console, 100);
2124
+#else
2125
ret = lxc_mainloop(&descr_console, 0);
2126
+#endif
2127
}
2128
2129
out_mainloop_console:
2130
2131
}
2132
2133
handler->name = name;
2134
+
2135
+#ifdef HAVE_ISULAD
2136
+ handler->exit_code = -1; /* isulad: record exit code of container */
2137
+ handler->image_type_oci = false;
2138
+#endif
2139
+
2140
if (daemonize)
2141
handler->transient_pid = lxc_raw_getpid();
2142
else
2143
2144
int ret;
2145
const char *loglevel;
2146
struct lxc_conf *conf = handler->conf;
2147
+#ifdef HAVE_ISULAD
2148
+ conf->console.disable_pty = handler->disable_pty;
2149
+ conf->console.open_stdin = handler->open_stdin;
2150
+#endif
2151
2152
handler->monitor_pid = lxc_raw_getpid();
2153
status_fd = open("/proc/self/status", O_RDONLY | O_CLOEXEC);
2154
2155
}
2156
}
2157
2158
+
2159
+#ifdef HAVE_ISULAD
2160
+/* isulad: start timeout thread */
2161
+typedef enum {
2162
+ START_INIT,
2163
+ START_TIMEOUT,
2164
+ START_MAX,
2165
+} start_timeout_t;
2166
+
2167
+static start_timeout_t global_timeout_state = START_INIT;
2168
+static sem_t global_timeout_sem;
2169
+
2170
+struct start_timeout_conf {
2171
+ unsigned int timeout;
2172
+ int errfd;
2173
+};
2174
+
2175
+void trim_line(char *s)
2176
+{
2177
+ size_t len;
2178
+
2179
+ len = strlen(s);
2180
+ while ((len > 1) && (s[len - 1] == '\n'))
2181
+ s[--len] = '\0';
2182
+}
2183
+
2184
+static int _read_procs_file(const char *path, pid_t **pids, size_t *len)
2185
+{
2186
+ FILE *f;
2187
+ char *line = NULL;
2188
+ size_t sz = 0;
2189
+ pid_t *tmp_pids = NULL;
2190
+
2191
+ f = fopen_cloexec(path, "r");
2192
+ if (!f)
2193
+ return -1;
2194
+
2195
+ while (getline(&line, &sz, f) != -1) {
2196
+ pid_t pid;
2197
+ trim_line(line);
2198
+ pid = (pid_t)atoll(line);
2199
+ if (lxc_mem_realloc((void **)&tmp_pids, sizeof(pid_t) * (*len + 1), *pids, sizeof(pid_t) * (*len)) != 0) {
2200
+ free(*pids);
2201
+ *pids = NULL;
2202
+ ERROR("out of memory");
2203
+ free(line);
2204
+ fclose(f);
2205
+ return -1;
2206
+ }
2207
+ *pids = tmp_pids;
2208
+
2209
+ (*pids)[*len] = pid;
2210
+ (*len)++;
2211
+ }
2212
+
2213
+ free(line);
2214
+ fclose(f);
2215
+ return 0;
2216
+}
2217
+
2218
+static int _recursive_read_cgroup_procs(const char *dirpath, pid_t **pids, size_t *len)
2219
+{
2220
+ struct dirent *direntp = NULL;
2221
+ DIR *dir = NULL;
2222
+ int ret, failed = 0;
2223
+ char pathname[PATH_MAX];
2224
+
2225
+ dir = opendir(dirpath);
2226
+ if (dir == NULL) {
2227
+ WARN("Failed to open \"%s\"", dirpath);
2228
+ return 0;
2229
+ }
2230
+
2231
+ while ((direntp = readdir(dir))) {
2232
+ struct stat mystat;
2233
+ int rc;
2234
+
2235
+ if (!strcmp(direntp->d_name, ".") ||
2236
+ !strcmp(direntp->d_name, ".."))
2237
+ continue;
2238
+
2239
+ rc = snprintf(pathname, PATH_MAX, "%s/%s", dirpath, direntp->d_name);
2240
+ if (rc < 0 || rc >= PATH_MAX) {
2241
+ failed = 1;
2242
+ continue;
2243
+ }
2244
+
2245
+ if (strcmp(direntp->d_name, "cgroup.procs") == 0) {
2246
+ if (_read_procs_file(pathname, pids, len)) {
2247
+ failed = 1;
2248
+
2249
+ }
2250
+ continue;
2251
+ }
2252
+
2253
+ ret = lstat(pathname, &mystat);
2254
+ if (ret) {
2255
+ failed = 1;
2256
+ continue;
2257
+ }
2258
+
2259
+ if (S_ISDIR(mystat.st_mode)) {
2260
+ if (_recursive_read_cgroup_procs(pathname, pids, len) < 0)
2261
+ failed = 1;
2262
+ }
2263
+ }
2264
+
2265
+ ret = closedir(dir);
2266
+ if (ret) {
2267
+ WARN("Failed to close directory \"%s\"", dirpath);
2268
+ failed = 1;
2269
+ }
2270
+
2271
+ return failed ? -1 : 0;
2272
+}
2273
+
2274
+int get_all_pids(struct cgroup_ops *cg_ops, pid_t **pids, size_t *len)
2275
+{
2276
+ const char *devices_path = NULL;
2277
+
2278
+ devices_path = cg_ops->get_cgroup_full_path(cg_ops, "devices");
2279
+ if (!file_exists(devices_path)) {
2280
+ return 0;
2281
+ }
2282
+
2283
+ return _recursive_read_cgroup_procs(devices_path, pids, len);
2284
+}
2285
+
2286
+static int set_cgroup_freezer(struct cgroup_ops *cg_ops, const char *value)
2287
+{
2288
+ char *fullpath;
2289
+ int ret;
2290
+
2291
+ fullpath = must_make_path(cg_ops->get_cgroup_full_path(cg_ops, "freezer"), "freezer.state", NULL);
2292
+ ret = lxc_write_to_file(fullpath, value, strlen(value), false, 0666);
2293
+ free(fullpath);
2294
+ return ret;
2295
+}
2296
+
2297
+/* isulad: kill all process in container cgroup path */
2298
+static void signal_all_processes(struct lxc_handler *handler)
2299
+{
2300
+ int ret;
2301
+ struct cgroup_ops *cg_ops = handler->cgroup_ops;
2302
+ pid_t *pids = NULL;
2303
+ size_t len = 0, i;
2304
+
2305
+ ret = set_cgroup_freezer(cg_ops, "FROZEN");
2306
+ if (ret < 0 && errno != ENOENT) {
2307
+ WARN("cgroup_set frozen failed");
2308
+ }
2309
+
2310
+ ret = get_all_pids(cg_ops, &pids, &len);
2311
+ if (ret < 0) {
2312
+ WARN("failed to get all pids");
2313
+ }
2314
+
2315
+ for (i = 0; i < len; i++) {
2316
+ ret = kill(pids[i], SIGKILL);
2317
+ if (ret < 0 && errno != ESRCH) {
2318
+ WARN("Can not kill process (pid=%d) with SIGKILL for container %s", pids[i], handler->name);
2319
+ }
2320
+ }
2321
+
2322
+ ret = set_cgroup_freezer(cg_ops, "THAWED");
2323
+ if (ret < 0 && errno != ENOENT) {
2324
+ WARN("cgroup_set thawed failed");
2325
+ }
2326
+
2327
+ for (i = 0; i < len; i++) {
2328
+ ret = lxc_wait_for_pid_status(pids[i]);
2329
+ if (ret < 0 && errno != ECHILD) {
2330
+ WARN("Failed to wait pid %d for container %s: %s", pids[i], handler->name, strerror(errno));
2331
+ }
2332
+ }
2333
+
2334
+ free(pids);
2335
+}
2336
+#endif
2337
+
2338
void lxc_end(struct lxc_handler *handler)
2339
{
2340
int ret;
2341
2342
2343
handler->lsm_ops->cleanup(handler->lsm_ops, handler->conf, handler->lxcpath);
2344
2345
+
2346
+#ifdef HAVE_ISULAD
2347
+ // close maincmd fd before destroy cgroup for isulad
2348
+ if (handler->conf->reboot == REBOOT_NONE) {
2349
+ /* For all new state clients simply close the command socket.
2350
+ * This will inform all state clients that the container is
2351
+ * STOPPED and also prevents a race between a open()/close() on
2352
+ * the command socket causing a new process to get ECONNREFUSED
2353
+ * because we haven't yet closed the command socket.
2354
+ */
2355
+ close_prot_errno_disarm(handler->conf->maincmd_fd);
2356
+ TRACE("Closed command socket");
2357
+ }
2358
+ int retry_count = 0;
2359
+ int max_retry = 10;
2360
+retry:
2361
+ if (cgroup_ops != NULL && !cgroup_ops->payload_destroy(cgroup_ops, handler)) {
2362
+ TRACE("Trying to kill all subprocess");
2363
+ signal_all_processes(handler);
2364
+ TRACE("Finished kill all subprocess");
2365
+ if (retry_count < max_retry) {
2366
+ usleep(100 * 1000); /* 100 millisecond */
2367
+ retry_count++;
2368
+ goto retry;
2369
+ }
2370
+ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
2371
+ }
2372
+#else
2373
if (cgroup_ops) {
2374
cgroup_ops->payload_destroy(cgroup_ops, handler);
2375
cgroup_ops->monitor_destroy(cgroup_ops, handler);
2376
}
2377
+#endif
2378
2379
put_lxc_rootfs(&handler->conf->rootfs, true);
2380
2381
if (handler->conf->reboot == REBOOT_NONE) {
2382
+#ifndef HAVE_ISULAD
2383
/* For all new state clients simply close the command socket.
2384
* This will inform all state clients that the container is
2385
* STOPPED and also prevents a race between a open()/close() on
2386
2387
*/
2388
close_prot_errno_disarm(handler->conf->maincmd_fd);
2389
TRACE("Closed command socket");
2390
+#endif
2391
2392
/* This function will try to connect to the legacy lxc-monitord
2393
* state server and only exists for backwards compatibility.
2394
*/
2395
lxc_monitor_send_state(name, STOPPED, handler->lxcpath);
2396
2397
+#ifdef HAVE_ISULAD
2398
+ /* isuald: write exit code to exit fifo */
2399
+ if (handler->conf->exit_fd >= 0) {
2400
+ ret = write(handler->conf->exit_fd, &handler->exit_code, sizeof(int));
2401
+ if (ret != sizeof(int)) {
2402
+ SYSERROR("Failed to write to exit code to exit fifo.");
2403
+ }
2404
+ }
2405
+#endif
2406
+
2407
/* The command socket is closed so no one can acces the command
2408
* socket anymore so there's no need to lock it.
2409
*/
2410
2411
2412
lxc_sync_fini_parent(handler);
2413
2414
+#ifdef HAVE_ISULAD
2415
+ sigset_t mask;
2416
+
2417
+ /*isulad: restore default signal handlers and unblock all signals*/
2418
+ for (int i = 1; i < NSIG; i++)
2419
+ signal(i, SIG_DFL);
2420
+
2421
+ ret = sigfillset(&mask);
2422
+ if (ret < 0) {
2423
+ SYSERROR("Failed to fill signal mask");
2424
+ goto out_warn_father;
2425
+ }
2426
+ ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
2427
+ if (ret < 0) {
2428
+ SYSERROR("Failed to set signal mask");
2429
+ goto out_warn_father;
2430
+ }
2431
+#endif
2432
+
2433
if (lxc_abstract_unix_recv_one_fd(data_sock1, &status_fd, NULL, 0) < 0) {
2434
ERROR("Failed to receive status file descriptor from parent process");
2435
goto out_warn_father;
2436
2437
* means that migration won't work, but at least we won't spew output
2438
* where it isn't wanted.
2439
*/
2440
+#ifdef HAVE_ISULAD
2441
+ if (!handler->disable_pty && handler->daemonize && !handler->conf->autodev) {
2442
+#else
2443
if (handler->daemonize && !handler->conf->autodev) {
2444
+#endif
2445
char path[PATH_MAX];
2446
2447
ret = strnprintf(path, sizeof(path), "%s/dev/null",
2448
2449
/* Setup the container, ip, names, utsname, ... */
2450
ret = lxc_setup(handler);
2451
if (ret < 0) {
2452
+#ifdef HAVE_ISULAD
2453
+ lxc_write_error_message(handler->conf->errpipe[1], "Failed to setup lxc, please check the config file.");
2454
+#endif
2455
ERROR("Failed to setup container \"%s\"", handler->name);
2456
goto out_warn_father;
2457
}
2458
2459
DEBUG("Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges");
2460
}
2461
2462
+#ifdef HAVE_ISULAD
2463
+ /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */
2464
+ if (handler->disable_pty) {
2465
+ if (handler->conf->console.pipes[0][1] >= 0) {
2466
+ close(handler->conf->console.pipes[0][1]);
2467
+ handler->conf->console.pipes[0][1] = -1;
2468
+ }
2469
+
2470
+ if (handler->conf->console.pipes[0][0] >= 0) {
2471
+ ret = dup2(handler->conf->console.pipes[0][0], STDIN_FILENO);
2472
+ if (ret < 0)
2473
+ goto out_warn_father;
2474
+ }
2475
+
2476
+ if (handler->conf->console.pipes[1][0] >= 0) {
2477
+ close(handler->conf->console.pipes[1][0]);
2478
+ handler->conf->console.pipes[1][0] = -1;
2479
+ }
2480
+
2481
+ if (handler->conf->console.pipes[1][1] >= 0) {
2482
+ ret = dup2(handler->conf->console.pipes[1][1], STDOUT_FILENO);
2483
+ if (ret < 0)
2484
+ goto out_warn_father;
2485
+ }
2486
+ if (handler->conf->console.pipes[2][0] >= 0) {
2487
+ close(handler->conf->console.pipes[2][0]);
2488
+ handler->conf->console.pipes[2][0] = -1;
2489
+ }
2490
+
2491
+ if (handler->conf->console.pipes[2][1] >= 0) {
2492
+ ret = dup2(handler->conf->console.pipes[2][1], STDERR_FILENO);
2493
+ if (ret < 0)
2494
+ goto out_warn_father;
2495
+ }
2496
+ }
2497
+#endif
2498
+
2499
/* If we mounted a temporary proc, then unmount it now. */
2500
tmp_proc_unmount(handler->conf);
2501
2502
2503
2504
close_prot_errno_disarm(handler->sigfd);
2505
2506
+#ifdef HAVE_ISULAD
2507
+ if (!handler->disable_pty && handler->conf->console.pty < 0 && handler->daemonize) {
2508
+#else
2509
if (handler->conf->console.pty < 0 && handler->daemonize) {
2510
+#endif
2511
if (devnull_fd < 0) {
2512
devnull_fd = open_devnull();
2513
if (devnull_fd < 0)
2514
2515
setsid();
2516
2517
if (handler->conf->init_cwd) {
2518
+#ifdef HAVE_ISULAD
2519
+ /* try to craete workdir if not exist */
2520
+ struct stat st;
2521
+ if (stat(handler->conf->init_cwd, &st) < 0 && mkdir_p(handler->conf->init_cwd, 0755) < 0) {
2522
+ SYSERROR("Try to create directory \"%s\" as workdir failed", handler->conf->init_cwd);
2523
+ lxc_write_error_message(handler->conf->errpipe[1], "%s:%d: Failed to create workdir: %s.",
2524
+ __FILE__, __LINE__, strerror(errno));
2525
+ goto out_warn_father;
2526
+ }
2527
+#endif
2528
ret = chdir(handler->conf->init_cwd);
2529
if (ret < 0) {
2530
SYSERROR("Could not change directory to \"%s\"",
2531
2532
}
2533
}
2534
2535
+#ifdef HAVE_ISULAD
2536
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
2537
+ SYSERROR("Failed to keep permitted capabilities");
2538
+ goto out_warn_father;
2539
+ }
2540
+#endif
2541
+
2542
/* The container has been setup. We can now switch to an unprivileged
2543
* uid/gid.
2544
*/
2545
new_uid = handler->conf->init_uid;
2546
new_gid = handler->conf->init_gid;
2547
2548
+#ifdef HAVE_ISULAD
2549
+ // isulad: set env home in container, must before "Avoid unnecessary syscalls."
2550
+ if (lxc_setup_env_home(new_uid) < 0) {
2551
+ goto out_warn_father;
2552
+ }
2553
+#endif
2554
+
2555
/* Avoid unnecessary syscalls. */
2556
if (new_uid == nsuid)
2557
new_uid = LXC_INVALID_UID;
2558
2559
goto out_warn_father;
2560
}
2561
2562
+#ifdef HAVE_ISULAD
2563
+ /* isulad: drop the cap of current process */
2564
+ if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
2565
+ SYSERROR("Failed to clear permitted capabilities");
2566
+ goto out_warn_father;
2567
+ }
2568
+
2569
+ if (lxc_drop_caps(handler->conf)) {
2570
+ SYSERROR("Failed to drop caps");
2571
+ goto out_warn_father;
2572
+ }
2573
+#endif
2574
+
2575
if (handler->conf->monitor_signal_pdeath != SIGKILL) {
2576
ret = lxc_set_death_signal(handler->conf->monitor_signal_pdeath,
2577
handler->monitor_pid, status_fd);
2578
2579
* After this call, we are in error because this ops should not return
2580
* as it execs.
2581
*/
2582
+#ifdef HAVE_ISULAD
2583
+ close_prot_errno_disarm(status_fd);
2584
+ handler->ops->start(handler, handler->data, handler->daemonize ? handler->conf->errpipe[1] : -1);
2585
+#else
2586
handler->ops->start(handler, handler->data);
2587
+#endif
2588
2589
out_warn_father:
2590
/*
2591
2592
handler->ns_unshare_flags |= CLONE_NEWCGROUP;
2593
}
2594
2595
+#ifdef HAVE_ISULAD
2596
+static int lxc_write_container_info(char *filename, pid_t pid, pid_t p_pid,
2597
+ unsigned long long start_at, unsigned long long p_start_at)
2598
+{
2599
+ FILE *pid_fp = NULL;
2600
+ int ret = 0;
2601
+
2602
+ pid_fp = lxc_fopen(filename, "w");
2603
+ if (pid_fp == NULL) {
2604
+ SYSERROR("Failed to create pidfile '%s'",filename);
2605
+ ret = -1;
2606
+ goto out;
2607
+ }
2608
+
2609
+ if (fprintf(pid_fp, "%d %llu %d %llu\n", pid, start_at, p_pid, p_start_at) < 0) {
2610
+ SYSERROR("Failed to write '%s'", filename);
2611
+ ret = -1;
2612
+ goto out;
2613
+ }
2614
+out:
2615
+ if (pid_fp)
2616
+ fclose(pid_fp);
2617
+ pid_fp = NULL;
2618
+ return ret;
2619
+}
2620
+
2621
+static int lxc_check_container_info(char *filename, pid_t pid, pid_t p_pid,
2622
+ unsigned long long start_at, unsigned long long p_start_at)
2623
+{
2624
+ int ret = 0;
2625
+ int num;
2626
+ char sbuf[1024] = {0}; /* bufs for stat */
2627
+ int saved_pid; /* process id */
2628
+ int saved_ppid; /* pid of parent process */
2629
+ unsigned long long saved_start_time; /* start time of process -- seconds since 1-1-70 */
2630
+ unsigned long long saved_pstart_time; /* start time of parent process -- seconds since 1-1-70 */
2631
+
2632
+ if ((lxc_file2str(filename, sbuf, sizeof(sbuf))) == -1) {
2633
+ SYSERROR("Failed to read pidfile %s", filename);
2634
+ ret = -1;
2635
+ goto out;
2636
+ }
2637
+
2638
+ num = sscanf(sbuf, "%d %Lu %d %Lu", &saved_pid, &saved_start_time, &saved_ppid, &saved_pstart_time);
2639
+ if (num != 4) {
2640
+ SYSERROR("Call sscanf error");
2641
+ ret = -1;
2642
+ goto out;
2643
+ }
2644
+
2645
+ if (pid != saved_pid || p_pid != saved_ppid
2646
+ || start_at != saved_start_time || p_start_at != saved_pstart_time) {
2647
+ ERROR("Check container info failed");
2648
+ ret = -1;
2649
+ goto out;
2650
+ }
2651
+
2652
+out:
2653
+ return ret;
2654
+}
2655
+
2656
+/* isuald: save pid/ppid info */
2657
+static int lxc_save_container_info(char *filename, pid_t pid)
2658
+{
2659
+ int ret = 0;
2660
+ pid_t p_pid = 0;
2661
+ unsigned long long start_at = 0;
2662
+ unsigned long long p_start_at = 0;
2663
+
2664
+ start_at = lxc_get_process_startat(pid);
2665
+ p_pid = getpid();
2666
+ p_start_at = lxc_get_process_startat(p_pid);
2667
+
2668
+ ret = lxc_write_container_info(filename, pid, p_pid, start_at, p_start_at);
2669
+ if (ret != 0) {
2670
+ goto out;
2671
+ }
2672
+
2673
+ ret = lxc_check_container_info(filename, pid, p_pid, start_at, p_start_at);
2674
+ if (ret != 0) {
2675
+ goto out;
2676
+ }
2677
+
2678
+out:
2679
+ return ret;
2680
+}
2681
+#endif
2682
+
2683
/* lxc_spawn() performs crucial setup tasks and clone()s the new process which
2684
* exec()s the requested container binary.
2685
* Note that lxc_spawn() runs in the parent namespaces. Any operations performed
2686
2687
handler->clone_flags &= ~CLONE_PIDFD;
2688
TRACE("Cloned child process %d", handler->pid);
2689
2690
+#ifdef HAVE_ISULAD
2691
+ /* isulad: close pipe after clone */
2692
+ if (handler->conf->console.pipes[0][0] >= 0) {
2693
+ close(handler->conf->console.pipes[0][0]);
2694
+ handler->conf->console.pipes[0][0] = -1;
2695
+ }
2696
+
2697
+ if (handler->conf->console.pipes[1][1] >= 0) {
2698
+ close(handler->conf->console.pipes[1][1]);
2699
+ handler->conf->console.pipes[1][1] = -1;
2700
+ }
2701
+
2702
+ if (handler->conf->console.pipes[2][1] >= 0) {
2703
+ close(handler->conf->console.pipes[2][1]);
2704
+ handler->conf->console.pipes[2][1] = -1;
2705
+ }
2706
+
2707
+ /* isulad: save pid/ppid info into file*/
2708
+ if (handler->conf->container_info_file) {
2709
+ if (lxc_save_container_info(handler->conf->container_info_file, handler->pid)) {
2710
+ ERROR("Failed to save cloned container pid");
2711
+ goto out_delete_net;
2712
+ }
2713
+ }
2714
+#endif
2715
+
2716
ret = core_scheduling(handler);
2717
if (ret < 0)
2718
goto out_delete_net;
2719
2720
if (ret < 0)
2721
SYSERROR("Failed to set environment variable: LXC_PID=%s", pidstr);
2722
2723
+#ifdef HAVE_ISULAD
2724
+ if (handler->cgroup_ops->container_cgroup) {
2725
+ if (setenv("LXC_CGROUP_PATH", handler->cgroup_ops->container_cgroup, 1))
2726
+ SYSERROR("Failed to set environment variable: LXC_CGROUP_PATH=%s.", handler->cgroup_ops->container_cgroup);
2727
+ }
2728
+#endif
2729
+
2730
for (i = 0; i < LXC_NS_MAX; i++)
2731
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
2732
INFO("Cloned %s", ns_info[i].flag_name);
2733
2734
goto out_delete_net;
2735
}
2736
2737
+#ifdef HAVE_ISULAD
2738
+ ret = setup_resource_limits(conf, handler->pid, conf->errpipe[1]);
2739
+#else
2740
ret = setup_resource_limits(conf, handler->pid);
2741
+#endif
2742
if (ret < 0) {
2743
ERROR("Failed to setup resource limits");
2744
goto out_delete_net;
2745
2746
goto out_delete_net;
2747
}
2748
2749
+#ifdef HAVE_ISULAD
2750
+ /* isulad: Run oci prestart hook at here */
2751
+ ret = run_oci_hooks(name, "oci-prestart", conf, lxcpath);
2752
+ if (ret < 0) {
2753
+ ERROR("Failed to run oci prestart hooks");
2754
+ goto out_delete_net;
2755
+ }
2756
+
2757
+ if (START_TIMEOUT == global_timeout_state) {
2758
+ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
2759
+ ERROR("Starting the container \"%s\" timeout.", name);
2760
+ goto out_delete_net;
2761
+ }
2762
+
2763
+ /* Tell the child to continue its initialization. We'll get
2764
+ * LXC_SYNC_POST_OCI_PRESTART_HOOK when it is ready for us to run oci prestart hooks.
2765
+ */
2766
+ if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_OCI_PRESTART_HOOK))
2767
+ goto out_delete_net;
2768
+#endif
2769
+
2770
if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
2771
goto out_delete_net;
2772
2773
2774
if (ret < 0)
2775
goto out_abort;
2776
2777
+#ifdef HAVE_ISULAD
2778
+ /* isulad: Run oci prestart hook at here */
2779
+ ret = run_oci_hooks(name, "oci-poststart", conf, lxcpath);
2780
+ if (ret < 0) {
2781
+ ERROR("Failed to run oci poststart hooks");
2782
+ goto out_abort;
2783
+ }
2784
+
2785
+ if (START_TIMEOUT == global_timeout_state) {
2786
+ lxc_write_error_message(conf->errpipe[1], "Starting the container \"%s\" timeout.", name);
2787
+ ERROR("Starting the container \"%s\" timeout.", name);
2788
+ goto out_abort;
2789
+ }
2790
+
2791
+#endif
2792
+
2793
ret = lxc_set_state(name, handler, RUNNING);
2794
if (ret < 0) {
2795
ERROR("Failed to set state to \"%s\"", lxc_state2str(RUNNING));
2796
2797
return 0;
2798
}
2799
2800
+#ifdef HAVE_ISULAD
2801
+/* isulad: start timeout thread function */
2802
+static void* wait_start_timeout(void *arg)
2803
+{
2804
+ struct start_timeout_conf *conf = (struct start_timeout_conf *)arg;
2805
+
2806
+ sem_post(&global_timeout_sem);
2807
+
2808
+ if (!conf || conf->timeout < 1)
2809
+ goto out;
2810
+
2811
+ sleep(conf->timeout);
2812
+
2813
+ global_timeout_state = START_TIMEOUT;
2814
+
2815
+out:
2816
+ free(conf);
2817
+ return ((void *)0);
2818
+}
2819
+
2820
+/* isulad: create start timeout thread */
2821
+static int create_start_timeout_thread(struct lxc_conf *conf, unsigned int start_timeout)
2822
+{
2823
+ int ret = 0;
2824
+ pthread_t ptid;
2825
+ pthread_attr_t attr;
2826
+ struct start_timeout_conf *timeout_conf = NULL;
2827
+
2828
+ if (sem_init(&global_timeout_sem, 0, 0)) {
2829
+ ERROR("Failed to init start timeout semaphore");/*lint !e613*/
2830
+ ret = -1;
2831
+ return ret;
2832
+ }
2833
+
2834
+ timeout_conf = malloc(sizeof(struct start_timeout_conf));
2835
+ if (timeout_conf == NULL) {
2836
+ ERROR("Failed to malloc start timeout conf");
2837
+ ret = -1;
2838
+ goto out;
2839
+ }
2840
+
2841
+ memset(timeout_conf, 0, sizeof(struct start_timeout_conf));
2842
+ timeout_conf->errfd = conf->errpipe[1];
2843
+ timeout_conf->timeout = start_timeout;
2844
+
2845
+ pthread_attr_init(&attr);
2846
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2847
+ ret = pthread_create(&ptid, &attr, wait_start_timeout, timeout_conf);
2848
+ pthread_attr_destroy(&attr);
2849
+ if (ret != 0) {
2850
+ ERROR("Create start wait timeout thread failed");
2851
+ free(timeout_conf);
2852
+ goto out;
2853
+ }
2854
+
2855
+ sem_wait(&global_timeout_sem);
2856
+out:
2857
+ sem_destroy(&global_timeout_sem);
2858
+ return ret;
2859
+}
2860
+
2861
+// isulad: send '128 + signal' if container is killed by signal.
2862
+#define EXIT_SIGNAL_OFFSET 128
2863
+#endif
2864
+
2865
+#ifdef HAVE_ISULAD
2866
+int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2867
+ void *data, const char *lxcpath, bool daemonize, int *error_num,
2868
+ unsigned int start_timeout)
2869
+{
2870
+ int exit_code;
2871
+#else
2872
int __lxc_start(struct lxc_handler *handler, struct lxc_operations *ops,
2873
void *data, const char *lxcpath, bool daemonize, int *error_num)
2874
{
2875
+#endif
2876
int ret, status;
2877
const char *name = handler->name;
2878
struct lxc_conf *conf = handler->conf;
2879
2880
handler->daemonize = daemonize;
2881
cgroup_ops = handler->cgroup_ops;
2882
2883
+#ifdef HAVE_ISULAD
2884
+ /* isulad: add start timeout limit */
2885
+ if (start_timeout > 0) {
2886
+ ret = create_start_timeout_thread(conf, start_timeout);
2887
+ if (ret) {
2888
+ ERROR("Failed to create start timeout thread for container \"%s\".", name);
2889
+ goto out_abort;
2890
+ }
2891
+ }
2892
+#endif
2893
+
2894
if (!attach_block_device(handler->conf)) {
2895
ERROR("Failed to attach block device");
2896
ret = -1;
2897
2898
goto out_delete_network;
2899
}
2900
2901
+#ifndef HAVE_ISULAD
2902
if (!handler->init_died && handler->pid > 0) {
2903
ERROR("Child process is not killed");
2904
ret = -1;
2905
goto out_delete_network;
2906
}
2907
+#endif
2908
2909
status = lxc_wait_for_pid_status(handler->pid);
2910
if (status < 0)
2911
2912
* reboot. This should mean it was an lxc-execute which simply exited.
2913
* In any case, treat it as a 'halt'.
2914
*/
2915
+#ifdef HAVE_ISULAD
2916
+ // isulad: recored log for container init exit
2917
+ if (WIFSIGNALED(status)) {
2918
+ int signal_nr = WTERMSIG(status);
2919
+ exit_code = EXIT_SIGNAL_OFFSET + signal_nr;
2920
+ ERROR("Container \"%s\" init exited with signal %d", name, signal_nr);
2921
+ } else if (WIFEXITED(status)) {
2922
+ exit_code = WEXITSTATUS(status);
2923
+ ERROR("Container \"%s\" init exited with status %d", name, exit_code);
2924
+ } else {
2925
+ exit_code = -1;
2926
+ ERROR("Container \"%s\" init exited with unknown status", name);
2927
+ }
2928
+#else
2929
if (WIFSIGNALED(status)) {
2930
int signal_nr = WTERMSIG(status);
2931
switch(signal_nr) {
2932
2933
break;
2934
}
2935
}
2936
+#endif
2937
2938
ret = lxc_restore_phys_nics_to_netns(handler);
2939
if (ret < 0)
2940
ERROR("Failed to move physical network devices back to parent network namespace");
2941
2942
+#ifdef HAVE_ISULAD
2943
+ lxc_monitor_send_exit_code(name, exit_code, handler->lxcpath);
2944
+#else
2945
lxc_monitor_send_exit_code(name, status, handler->lxcpath);
2946
+#endif
2947
lxc_error_set_and_log(handler->pid, status);
2948
if (error_num)
2949
*error_num = handler->exit_status;
2950
2951
+#ifdef HAVE_ISULAD
2952
+ handler->exit_code = exit_code; /* record exit code */
2953
+#endif
2954
+
2955
lxc_delete_network(handler);
2956
detach_block_device(handler->conf);
2957
lxc_end(handler);
2958
2959
char *const *argv;
2960
};
2961
2962
+#ifdef HAVE_ISULAD
2963
+static int start(struct lxc_handler *handler, void* data, int fd)
2964
+#else
2965
static int start(struct lxc_handler *handler, void* data)
2966
+#endif
2967
{
2968
struct start_args *arg = data;
2969
2970
2971
2972
execvp(arg->argv[0], arg->argv);
2973
SYSERROR("Failed to exec \"%s\"", arg->argv[0]);
2974
+#ifdef HAVE_ISULAD
2975
+ lxc_write_error_message(fd, "exec: \"%s\": %s.", arg->argv[0], strerror(errno));
2976
+#endif
2977
return 0;
2978
}
2979
2980
2981
};
2982
2983
int lxc_start(char *const argv[], struct lxc_handler *handler,
2984
+#ifdef HAVE_ISULAD
2985
+ const char *lxcpath, bool daemonize, int *error_num, unsigned int start_timeout)
2986
+#else
2987
const char *lxcpath, bool daemonize, int *error_num)
2988
+#endif
2989
{
2990
struct start_args start_arg = {
2991
.argv = argv,
2992
};
2993
2994
TRACE("Doing lxc_start");
2995
+#ifdef HAVE_ISULAD
2996
+ return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num, start_timeout);
2997
+#else
2998
return __lxc_start(handler, &start_ops, &start_arg, lxcpath, daemonize, error_num);
2999
+#endif
3000
}
3001
3002
static void lxc_destroy_container_on_signal(struct lxc_handler *handler,
3003
3004
3005
return storage_destroy(handler->conf);
3006
}
3007
+
3008
+#ifdef HAVE_ISULAD
3009
+/*isulad: set env for clean resources */
3010
+static int clean_resource_set_env(struct lxc_handler *handler)
3011
+{
3012
+ const char *name = handler->name;
3013
+ struct lxc_conf *conf = handler->conf;
3014
+ char bufstr[PATH_MAX + 1];
3015
+ int i = 0;
3016
+ int j = 0;
3017
+ int len = 2; //set "LXC_PID" and "LXC_CGNS_AWARE"
3018
+
3019
+ if (conf == NULL || conf->ocihooks == NULL || conf->ocihooks->poststop_len == 0) {
3020
+ return 0;
3021
+ }
3022
+
3023
+ if (name) {
3024
+ len++;
3025
+ }
3026
+ if (conf->rcfile) {
3027
+ len++;
3028
+ }
3029
+ if (conf->rootfs.mount) {
3030
+ len++;
3031
+ }
3032
+ if (conf->rootfs.path) {
3033
+ len++;
3034
+ }
3035
+ if (conf->console.path) {
3036
+ len++;
3037
+ }
3038
+ if (conf->console.log_path) {
3039
+ len++;
3040
+ }
3041
+ if (handler->cgroup_ops->container_cgroup) {
3042
+ len++;
3043
+ }
3044
+
3045
+ for (; i < conf->ocihooks->poststop_len; i++) {
3046
+ size_t cap = conf->ocihooks->poststop[i]->env_len;
3047
+ size_t newcap = cap + len + 1;
3048
+ if (lxc_grow_array((void ***)&(conf->ocihooks->poststop[i]->env), &cap, newcap, 1) != 0) {
3049
+ return -1;
3050
+ }
3051
+ j = conf->ocihooks->poststop[i]->env_len;
3052
+ /* Start of environment variable setup for hooks. */
3053
+ if (name) {
3054
+ snprintf(bufstr, PATH_MAX + 1, "LXC_NAME=%s", name);
3055
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3056
+ }
3057
+ if (conf->rcfile) {
3058
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONFIG_FILE=%s", conf->rcfile);
3059
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3060
+ }
3061
+ if (conf->rootfs.mount) {
3062
+ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_MOUNT=%s", conf->rootfs.mount);
3063
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3064
+ }
3065
+ if (conf->rootfs.path) {
3066
+ snprintf(bufstr, PATH_MAX + 1, "LXC_ROOTFS_PATH=%s", conf->rootfs.path);
3067
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3068
+ }
3069
+ if (conf->console.path) {
3070
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE=%s", conf->console.path);
3071
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3072
+ }
3073
+ if (conf->console.log_path) {
3074
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CONSOLE_LOGPATH=%s", conf->console.log_path);
3075
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3076
+ }
3077
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup("LXC_CGNS_AWARE=1");
3078
+
3079
+ snprintf(bufstr, PATH_MAX + 1, "LXC_PID=%d", handler->pid);
3080
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3081
+ if (handler->cgroup_ops->container_cgroup) {
3082
+ snprintf(bufstr, PATH_MAX + 1, "LXC_CGROUP_PATH=%s", handler->cgroup_ops->container_cgroup);
3083
+ conf->ocihooks->poststop[i]->env[j++] = safe_strdup(bufstr);
3084
+ }
3085
+ conf->ocihooks->poststop[i]->env_len = j;
3086
+ /* End of environment variable setup for hooks. */
3087
+ }
3088
+ return 0;
3089
+}
3090
+
3091
+/*isulad: init handler for clean */
3092
+static struct lxc_handler *lxc_init_clean_handler(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
3093
+{
3094
+ int i;
3095
+ struct lxc_handler *handler;
3096
+
3097
+ handler = malloc(sizeof(*handler));
3098
+ if (handler == NULL)
3099
+ return NULL;
3100
+
3101
+ memset(handler, 0, sizeof(*handler));
3102
+
3103
+ /* Note that am_guest_unpriv() checks the effective uid. We
3104
+ * probably don't care if we are real root only if we are running
3105
+ * as root so this should be fine.
3106
+ */
3107
+ handler->am_root = !am_guest_unpriv();
3108
+ handler->data_sock[0] = handler->data_sock[1] = -1;
3109
+ handler->conf = conf;
3110
+ handler->lxcpath = lxcpath;
3111
+ handler->pinfd = -1;
3112
+ handler->sigfd = -EBADF;
3113
+ handler->pidfd = -EBADF;
3114
+ handler->init_died = false;
3115
+ handler->monitor_status_fd = -EBADF;
3116
+ handler->pid = pid;
3117
+ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
3118
+ if (handler->conf->reboot == REBOOT_NONE)
3119
+ lxc_list_init(&handler->conf->state_clients);
3120
+
3121
+ for (i = 0; i < LXC_NS_MAX; i++)
3122
+ handler->nsfd[i] = -1;
3123
+
3124
+ handler->name = name;
3125
+ handler->exit_code = -1; /* isulad: record exit code of container */
3126
+
3127
+ handler->cgroup_ops = cgroup_init(conf);
3128
+ if (!handler->cgroup_ops) {
3129
+ ERROR("Failed to initialize cgroup driver");
3130
+ goto on_error;
3131
+ }
3132
+
3133
+ INFO("Container \"%s\" 's clean handler is initialized.", name);
3134
+
3135
+ return handler;
3136
+
3137
+on_error:
3138
+ lxc_put_handler(handler);
3139
+
3140
+ return NULL;
3141
+}
3142
+
3143
+/*isulad: init handler for clean */
3144
+static struct lxc_handler *lxc_init_pids_handler(char *name, char *lxcpath, struct lxc_conf *conf)
3145
+{
3146
+ int i;
3147
+ struct lxc_handler *handler;
3148
+
3149
+ handler = malloc(sizeof(*handler));
3150
+ if (handler == NULL)
3151
+ return NULL;
3152
+
3153
+ memset(handler, 0, sizeof(*handler));
3154
+
3155
+ /* Note that am_guest_unpriv() checks the effective uid. We
3156
+ * probably don't care if we are real root only if we are running
3157
+ * as root so this should be fine.
3158
+ */
3159
+ handler->am_root = !am_guest_unpriv();
3160
+ handler->data_sock[0] = handler->data_sock[1] = -1;
3161
+ handler->conf = conf;
3162
+ handler->lxcpath = lxcpath;
3163
+ handler->pinfd = -1;
3164
+ handler->sigfd = -EBADF;
3165
+ handler->init_died = false;
3166
+ handler->state_socket_pair[0] = handler->state_socket_pair[1] = -1;
3167
+ handler->monitor_status_fd = -EBADF;
3168
+ handler->pidfd = -EBADF;
3169
+ if (handler->conf->reboot == REBOOT_NONE)
3170
+ lxc_list_init(&handler->conf->state_clients);
3171
+
3172
+ for (i = 0; i < LXC_NS_MAX; i++)
3173
+ handler->nsfd[i] = -1;
3174
+
3175
+ handler->name = name;
3176
+ handler->exit_code = -1; /* isulad: record exit code of container */
3177
+
3178
+ handler->cgroup_ops = cgroup_init(conf);
3179
+ if (!handler->cgroup_ops) {
3180
+ ERROR("Failed to initialize cgroup driver");
3181
+ goto on_error;
3182
+ }
3183
+
3184
+ INFO("Container \"%s\" 's clean handler is initialized.", name);
3185
+
3186
+ return handler;
3187
+
3188
+on_error:
3189
+ lxc_put_handler(handler);
3190
+
3191
+ return NULL;
3192
+}
3193
+
3194
+/*isulad: do_lxcapi_clean_resource */
3195
+int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid)
3196
+{
3197
+ int ret = 0;
3198
+ struct lxc_handler *handler = NULL;
3199
+ int retry_count = 0;
3200
+ int max_retry = 10;
3201
+
3202
+ handler = lxc_init_clean_handler(name, lxcpath, conf, pid);
3203
+ if (!handler) {
3204
+ ERROR("Failed to init container %s clean handler", name);
3205
+ ret = -1;
3206
+ goto out;
3207
+ }
3208
+
3209
+ if (clean_resource_set_env(handler) != 0) {
3210
+ ERROR("Failed to set env for poststop hooks");
3211
+ ret = -1;
3212
+ goto out;
3213
+ }
3214
+
3215
+ if (run_oci_hooks(handler->name, "oci-poststop", handler->conf, handler->lxcpath)) {
3216
+ ERROR("Failed to run lxc.hook.post-stop for container \"%s\".", handler->name);
3217
+ ret = -1;
3218
+ }
3219
+
3220
+retry:
3221
+ if (!handler->cgroup_ops->payload_destroy(handler->cgroup_ops, handler)) {
3222
+ TRACE("Trying to kill all subprocess");
3223
+ signal_all_processes(handler);
3224
+ TRACE("Finished kill all subprocess");
3225
+ if (retry_count < max_retry) {
3226
+ usleep(100 * 1000); /* 100 millisecond */
3227
+ retry_count++;
3228
+ goto retry;
3229
+ }
3230
+ SYSERROR("Failed to destroy cgroup path for container: \"%s\"", handler->name);
3231
+ ret = -1;
3232
+ }
3233
+
3234
+out:
3235
+ lxc_put_handler(handler);
3236
+ return ret;
3237
+}
3238
+
3239
+/*isulad: do_lxcapi_get_pids */
3240
+int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len)
3241
+{
3242
+ int ret = 0;
3243
+ struct lxc_handler *handler = NULL;
3244
+ struct cgroup_ops *cg_ops = NULL;
3245
+
3246
+ handler = lxc_init_pids_handler(name, lxcpath, conf);
3247
+ if (!handler) {
3248
+ ERROR("Failed to init container %s clean handler", name);
3249
+ ret = -1;
3250
+ goto out;
3251
+ }
3252
+
3253
+ cg_ops = handler->cgroup_ops;
3254
+ ret = get_all_pids(cg_ops, pids, pids_len);
3255
+ if (ret < 0) {
3256
+ WARN("failed to get all pids");
3257
+ }
3258
+
3259
+out:
3260
+ lxc_put_handler(handler);
3261
+ return ret;
3262
+}
3263
+
3264
+#endif
3265
diff --git a/src/lxc/start.h b/src/lxc/start.h
3266
index bbd1a83..d03e5d5 100644
3267
--- a/src/lxc/start.h
3268
+++ b/src/lxc/start.h
3269
3270
};
3271
3272
struct lxc_operations {
3273
+#ifdef HAVE_ISULAD
3274
+ int (*start)(struct lxc_handler *, void *, int);
3275
+#else
3276
int (*start)(struct lxc_handler *, void *);
3277
+#endif
3278
int (*post_start)(struct lxc_handler *, void *);
3279
};
3280
3281
3282
ARRAY_SIZE(handler->keep_fds));
3283
}
3284
3285
+#ifdef HAVE_ISULAD
3286
+__hidden extern int __lxc_start(struct lxc_handler *handler,
3287
+ struct lxc_operations* ops, void *data, const char *lxcpath,
3288
+ bool daemonize, int *error_num, unsigned int start_timeout);
3289
+#else
3290
__hidden extern int __lxc_start(struct lxc_handler *, struct lxc_operations *, void *, const char *,
3291
bool, int *);
3292
+#endif
3293
3294
__hidden extern int resolve_clone_flags(struct lxc_handler *handler);
3295
__hidden extern void lxc_expose_namespace_environment(const struct lxc_handler *handler);
3296
3297
+#ifdef HAVE_ISULAD
3298
+/*isulad: do_lxcapi_clean_resource */
3299
+extern int do_lxcapi_clean_resource(char *name, char *lxcpath, struct lxc_conf *conf, pid_t pid);
3300
+
3301
+/*isulad: do_lxcapi_get_pids */
3302
+extern int do_lxcapi_get_pids(char *name, char *lxcpath, struct lxc_conf *conf, pid_t **pids,size_t *pids_len);
3303
+#endif
3304
+
3305
static inline bool container_uses_namespace(const struct lxc_handler *handler,
3306
unsigned int ns_flag)
3307
{
3308
--
3309
2.25.1
3310
3311