!9 lcr: internal change at 1.6
Merge pull request !9 from lifeng_isula/3.6
This commit is contained in:
commit
3e885a4b12
@ -5,7 +5,7 @@ include(cmake/set_build_flags.cmake)
|
||||
|
||||
option(VERSION "set lcr version" ON)
|
||||
if (VERSION STREQUAL "ON")
|
||||
set(LCR_VERSION "1.0.18")
|
||||
set(LCR_VERSION "1.0.20")
|
||||
endif()
|
||||
|
||||
option(DEBUG "set lcr gcc option" ON)
|
||||
|
||||
6
lcr.spec
6
lcr.spec
@ -1,5 +1,5 @@
|
||||
%global _version 1.0.18
|
||||
%global _release 20200120.104405.git2310fafe
|
||||
%global _version 1.0.20
|
||||
%global _release 20200215.125545.git330d8cda
|
||||
Name: lcr
|
||||
Version: %{_version}
|
||||
Release: %{_release}
|
||||
@ -15,7 +15,7 @@ BuildRequires: lxc
|
||||
BuildRequires: lxc-devel
|
||||
BuildRequires: yajl yajl-devel
|
||||
BuildRequires: python3
|
||||
Requires: rsync bridge-utils lxc
|
||||
Requires: lxc
|
||||
ExclusiveArch: x86_64 aarch64
|
||||
|
||||
%ifarch x86_64
|
||||
|
||||
@ -627,7 +627,7 @@ static int trans_oci_process_selinux(const oci_runtime_spec_process *proc, struc
|
||||
int ret = -1;
|
||||
|
||||
if (proc->selinux_label != NULL) {
|
||||
node = create_lcr_list_node("lxc.se_context", proc->selinux_label);
|
||||
node = create_lcr_list_node("lxc.selinux.context", proc->selinux_label);
|
||||
if (node == NULL) {
|
||||
goto out;
|
||||
}
|
||||
@ -1000,7 +1000,7 @@ err_out:
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool is_system_container(const oci_runtime_spec *container)
|
||||
bool is_system_container(const oci_runtime_spec *container)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) {
|
||||
@ -1279,7 +1279,7 @@ static int trans_resources_mem_swap(const oci_runtime_config_linux_resources *re
|
||||
}
|
||||
}
|
||||
|
||||
if (res->memory->swappiness != INVALID_INT) {
|
||||
if (res->memory->swappiness != -1) {
|
||||
/* set swappiness parameter of vmscan */
|
||||
nret = trans_conf_uint64(conf, "lxc.cgroup.memory.swappiness", res->memory->swappiness);
|
||||
if (nret < 0) {
|
||||
|
||||
@ -107,4 +107,7 @@ struct lcr_list *trans_annotations(const json_map_string_string *anno);
|
||||
*/
|
||||
struct lcr_list *get_needed_lxc_conf();
|
||||
|
||||
#endif /* __LCR_CONF_H */
|
||||
|
||||
bool is_system_container(const oci_runtime_spec *container);
|
||||
|
||||
#endif /*__LCR_CONF_H*/
|
||||
|
||||
@ -22,6 +22,16 @@ History: 2019-06-17
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
|
||||
CODE = '''// Auto generated file. Do not edit!
|
||||
# define _GNU_SOURCE
|
||||
|
||||
@ -23,6 +23,15 @@ History: 2019-06-17
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
#!/usr/bin/python -Es
|
||||
|
||||
"""
|
||||
|
||||
@ -22,6 +22,16 @@ History: 2019-06-17
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
|
||||
import traceback
|
||||
import os
|
||||
|
||||
@ -23,6 +23,16 @@ History: 2019-06-17
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
#
|
||||
#!/usr/bin/python -Es
|
||||
import helpers
|
||||
|
||||
|
||||
@ -23,6 +23,15 @@ History: 2019-06-17
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
#!/usr/bin/python -Es
|
||||
import os
|
||||
import sys
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2017 Giuseppe Scrivano
|
||||
Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved.
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2017 Giuseppe Scrivano
|
||||
Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved.
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
@ -19,6 +19,15 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with libocispec. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, you may create a larger work that contains
|
||||
# part or all of the libocispec parser skeleton and distribute that work
|
||||
# under terms of your choice, so long as that work isn't itself a
|
||||
# parser generator using the skeleton or a modified version thereof
|
||||
# as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
# the parser skeleton itself, you may (at your option) remove this
|
||||
# special exception, which will cause the skeleton and the resulting
|
||||
# libocispec output files to be licensed under the GNU General Public
|
||||
# License without this special exception.
|
||||
import helpers
|
||||
|
||||
|
||||
|
||||
@ -33,9 +33,7 @@
|
||||
#include "lcrcontainer_extend.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include "oci_runtime_hooks.h"
|
||||
#include "oci_runtime_spec.h"
|
||||
#include "start_generate_config.h"
|
||||
|
||||
/*
|
||||
* Free lcr_container_info array returned by lcr_list_{active,all}_containers
|
||||
@ -172,582 +170,6 @@ int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **inf
|
||||
return (int)info_size;
|
||||
}
|
||||
|
||||
static bool create_container_dir(const struct lxc_container *c)
|
||||
{
|
||||
bool ret = false;
|
||||
int nret;
|
||||
char *s = NULL;
|
||||
mode_t mask = umask(S_IWOTH);
|
||||
size_t length = 0;
|
||||
|
||||
if (strlen(c->name) > ((SIZE_MAX - strlen(c->config_path)) - 2)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
length = strlen(c->config_path) + strlen(c->name) + 2;
|
||||
s = util_common_calloc_s(length);
|
||||
if (s == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
nret = snprintf(s, length, "%s/%s", c->config_path, c->name);
|
||||
if (nret < 0 || (size_t)nret >= length) {
|
||||
goto out;
|
||||
}
|
||||
// create container dir
|
||||
nret = util_mkdir_p(s, CONFIG_DIRECTORY_MODE);
|
||||
if (nret != 0 && errno != EEXIST) {
|
||||
SYSERROR("Failed to create container path %s", s);
|
||||
goto out;
|
||||
}
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
free(s);
|
||||
umask(mask);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool remove_container_dir(const struct lxc_container *c)
|
||||
{
|
||||
char *s = NULL;
|
||||
int ret = 0;
|
||||
size_t length = 0;
|
||||
|
||||
if (strlen(c->name) > ((SIZE_MAX - strlen(c->config_path)) - 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
length = strlen(c->config_path) + strlen(c->name) + 2;
|
||||
s = util_common_calloc_s(length);
|
||||
if (s == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = snprintf(s, length, "%s/%s", c->config_path, c->name);
|
||||
if (ret < 0 || (size_t)ret >= length) {
|
||||
free(s);
|
||||
return false;
|
||||
}
|
||||
ret = util_recursive_rmdir(s, 0);
|
||||
free(s);
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lcr_write_file(const char *path, const char *data, size_t len)
|
||||
{
|
||||
char *real_path = NULL;
|
||||
int fd = -1;
|
||||
int ret = -1;
|
||||
|
||||
if (path == NULL || strlen(path) == 0 || data == NULL || len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (util_ensure_path(&real_path, path) < 0) {
|
||||
ERROR("Failed to ensure path %s", path);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fd = util_open(real_path, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
||||
if (fd == -1) {
|
||||
ERROR("Create file %s failed", real_path);
|
||||
lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", real_path);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (write(fd, data, len) == -1) {
|
||||
ERROR("write data to %s failed: %s", real_path, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
}
|
||||
free(real_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool lcr_write_ocihooks(const char *path, const oci_runtime_spec_hooks *hooks)
|
||||
{
|
||||
bool ret = false;
|
||||
struct parser_context ctx = { OPT_PARSE_STRICT, stderr };
|
||||
parser_error err = NULL;
|
||||
|
||||
char *json_hooks = oci_runtime_spec_hooks_generate_json(hooks, &ctx, &err);
|
||||
if (json_hooks == NULL) {
|
||||
ERROR("Failed to generate json: %s", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (lcr_write_file(path, json_hooks, strlen(json_hooks)) == -1) {
|
||||
ERROR("write json hooks failed: %s", strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out_free:
|
||||
free(err);
|
||||
free(json_hooks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool lcr_save_ocihooks(const char *name, const char *lcrpath, const oci_runtime_spec_hooks *hooks)
|
||||
{
|
||||
const char *path = lcrpath ? lcrpath : LCRPATH;
|
||||
char ocihook[PATH_MAX] = { 0 };
|
||||
char *bundle = NULL;
|
||||
bool bret = false;
|
||||
int nret = 0;
|
||||
|
||||
if (name == NULL) {
|
||||
ERROR("Missing name");
|
||||
return false;
|
||||
}
|
||||
|
||||
bundle = lcr_get_bundle(path, name);
|
||||
if (bundle == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nret = snprintf(ocihook, sizeof(ocihook), "%s/%s", bundle, OCIHOOKSFILE);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(ocihook)) {
|
||||
ERROR("Failed to print string");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
bret = lcr_write_ocihooks(ocihook, hooks);
|
||||
|
||||
out_free:
|
||||
free(bundle);
|
||||
return bret;
|
||||
}
|
||||
|
||||
static bool lcr_write_container(const char *path, const oci_runtime_spec *container)
|
||||
{
|
||||
bool ret = false;
|
||||
struct parser_context ctx = { OPT_PARSE_STRICT, stderr };
|
||||
parser_error err = NULL;
|
||||
|
||||
char *json_container = oci_runtime_spec_generate_json(container, &ctx, &err);
|
||||
if (json_container == NULL) {
|
||||
ERROR("Failed to generate json: %s", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (lcr_write_file(path, json_container, strlen(json_container)) == -1) {
|
||||
ERROR("write json container failed: %s", strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out_free:
|
||||
free(err);
|
||||
free(json_container);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool lcr_save_container(const char *name, const char *lcrpath, const oci_runtime_spec *container)
|
||||
{
|
||||
bool bret = false;
|
||||
const char *path = lcrpath ? lcrpath : LCRPATH;
|
||||
char ociconfig[PATH_MAX] = { 0 };
|
||||
char *bundle = NULL;
|
||||
int nret = 0;
|
||||
|
||||
if (name == NULL) {
|
||||
ERROR("Missing name");
|
||||
return bret;
|
||||
}
|
||||
|
||||
bundle = lcr_get_bundle(path, name);
|
||||
if (bundle == NULL) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
nret = snprintf(ociconfig, sizeof(ociconfig), "%s/%s", bundle, OCICONFIGFILE);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(ociconfig)) {
|
||||
ERROR("Failed to print string");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
bret = lcr_write_container(ociconfig, container);
|
||||
|
||||
out_free:
|
||||
free(bundle);
|
||||
return bret;
|
||||
}
|
||||
/*
|
||||
* Expand array for container->mounts
|
||||
*/
|
||||
static bool mounts_expand(oci_runtime_spec *container, size_t add_len)
|
||||
{
|
||||
defs_mount **tmp_mount = NULL;
|
||||
int ret = 0;
|
||||
size_t old_len = container->mounts_len;
|
||||
if (add_len >= SIZE_MAX / sizeof(defs_mount *) - old_len) {
|
||||
ERROR("Too many mount elements!");
|
||||
return false;
|
||||
}
|
||||
ret = mem_realloc((void **)&tmp_mount, (old_len + add_len) * sizeof(defs_mount *), container->mounts,
|
||||
old_len * sizeof(defs_mount *));
|
||||
if (ret == -1) {
|
||||
ERROR("memory realloc failed for mount array expand");
|
||||
return false;
|
||||
}
|
||||
container->mounts = tmp_mount;
|
||||
container->mounts_len = old_len + add_len;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Get the file path that needs to be mount
|
||||
*/
|
||||
static bool mount_get_bundle_file(char **bundle, const char *container_name, const char *lcrpath, const char *filename)
|
||||
{
|
||||
const char *path = lcrpath ? lcrpath : LCRPATH;
|
||||
int nret = 0;
|
||||
size_t len = 0;
|
||||
|
||||
if (strlen(container_name) > (((SIZE_MAX - strlen(path)) - strlen(filename)) - 3)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* bundle = lcrpath + '/' + container_name + '/' + filename + '\0' */
|
||||
len = strlen(path) + strlen(container_name) + strlen(filename) + 3;
|
||||
*bundle = util_common_calloc_s(len);
|
||||
if (*bundle == NULL) {
|
||||
return false;
|
||||
}
|
||||
nret = snprintf(*bundle, len, "%s/%s/%s", path, container_name, filename);
|
||||
if (nret < 0 || (size_t)nret >= len) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* Mount file
|
||||
*/
|
||||
static bool mount_file(oci_runtime_spec *container, const char *bundle, const char *filename, const char *targetdir)
|
||||
{
|
||||
char dest[PATH_MAX] = { 0 };
|
||||
char **options = NULL;
|
||||
size_t options_len = 2;
|
||||
bool ret = false;
|
||||
int nret = 0;
|
||||
defs_mount *tmp_mounts = NULL;
|
||||
|
||||
nret = snprintf(dest, sizeof(dest), "%s/%s", targetdir, filename);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(dest)) {
|
||||
ERROR("Failed to print string");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (options_len > (SIZE_MAX / sizeof(char *))) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
options = util_common_calloc_s(options_len * sizeof(char *));
|
||||
if (options == NULL) {
|
||||
ERROR("Out of memory");
|
||||
goto out_free;
|
||||
}
|
||||
options[0] = util_strdup_s("rbind");
|
||||
options[1] = util_strdup_s("rprivate");
|
||||
/* generate mount node */
|
||||
tmp_mounts = util_common_calloc_s(sizeof(defs_mount));
|
||||
if (tmp_mounts == NULL) {
|
||||
ERROR("Malloc tmp_mounts memory failed");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
tmp_mounts->destination = util_strdup_s(dest);
|
||||
tmp_mounts->source = util_strdup_s(bundle);
|
||||
tmp_mounts->type = util_strdup_s("bind");
|
||||
tmp_mounts->options = options;
|
||||
tmp_mounts->options_len = options_len;
|
||||
options = NULL;
|
||||
|
||||
/* expand mount array */
|
||||
if (!mounts_expand(container, 1)) {
|
||||
goto out_free;
|
||||
}
|
||||
/* add a new mount node */
|
||||
container->mounts[container->mounts_len - 1] = tmp_mounts;
|
||||
|
||||
ret = true;
|
||||
out_free:
|
||||
|
||||
if (!ret) {
|
||||
util_free_array(options);
|
||||
free_defs_mount(tmp_mounts);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount hostname file to /etc/hostname
|
||||
*/
|
||||
static bool mount_hostname(oci_runtime_spec *container, const struct lxc_container *c)
|
||||
{
|
||||
bool ret = true;
|
||||
char *bundle = NULL;
|
||||
char *filename = "hostname";
|
||||
char *targetdir = "/etc";
|
||||
|
||||
if (container == NULL || container->hostname == NULL) {
|
||||
return true;
|
||||
}
|
||||
/* 1.get file path for hostname */
|
||||
ret = mount_get_bundle_file(&bundle, c->name, c->config_path, filename);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
/* 2.generate hostname file that need to mount */
|
||||
ret = util_write_file(bundle, container->hostname, strlen(container->hostname),
|
||||
true, NETWORK_MOUNT_FILE_MODE);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
/* 3.Add one mount nodes to container->mounts */
|
||||
ret = mount_file(container, bundle, filename, targetdir);
|
||||
if (!ret) {
|
||||
ERROR("mount hostname file failed");
|
||||
goto out_free;
|
||||
}
|
||||
out_free:
|
||||
free(bundle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount network file, such as hosts, resolv.conf
|
||||
*/
|
||||
static bool mount_network_file(oci_runtime_spec *container, const struct lxc_container *c, const char *full_path,
|
||||
const char *default_str)
|
||||
{
|
||||
bool ret = false;
|
||||
char *bundle = NULL;
|
||||
char *filename = NULL;
|
||||
char *targetdir = NULL;
|
||||
|
||||
if (full_path == NULL) {
|
||||
return false;
|
||||
}
|
||||
targetdir = util_strdup_s(full_path);
|
||||
filename = strrchr(targetdir, '/');
|
||||
if (filename == NULL) {
|
||||
ERROR("Invalid path: %s", targetdir);
|
||||
goto out_free;
|
||||
}
|
||||
*filename = '\0';
|
||||
filename += 1;
|
||||
// 1. get file path for hosts
|
||||
ret = mount_get_bundle_file(&bundle, c->name, c->config_path, filename);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
// 2. copy /etc/hosts into container hosts file that need to mount
|
||||
if (file_exists(full_path)) {
|
||||
ret = util_copy_file(full_path, bundle, NETWORK_MOUNT_FILE_MODE);
|
||||
} else {
|
||||
// write default value into bundle
|
||||
if (default_str != NULL && strlen(default_str) > 0) {
|
||||
ret = util_write_file(bundle, default_str, strlen(default_str), false, NETWORK_MOUNT_FILE_MODE);
|
||||
} else {
|
||||
ret = false;
|
||||
ERROR("Default value is NULL");
|
||||
}
|
||||
}
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
// 3. Add one mount nodes to container->mounts
|
||||
ret = mount_file(container, bundle, filename, targetdir);
|
||||
if (!ret) {
|
||||
ERROR("mount hostname file failed");
|
||||
goto out_free;
|
||||
}
|
||||
out_free:
|
||||
free(targetdir);
|
||||
free(bundle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mount hosts file to /etc/hosts
|
||||
*/
|
||||
static bool mount_hosts(oci_runtime_spec *container, const struct lxc_container *c)
|
||||
{
|
||||
bool ret = false;
|
||||
char *bundle = NULL;
|
||||
char *content = NULL;
|
||||
char *filename = "hosts";
|
||||
char *targetdir = "/etc";
|
||||
size_t content_len = 0;
|
||||
int nret = 0;
|
||||
const char *default_config = "127.0.0.1 localhost\n"
|
||||
"::1 localhost ip6-localhost ip6-loopback\n"
|
||||
"fe00::0 ip6-localnet\n"
|
||||
"ff00::0 ip6-mcastprefix\n"
|
||||
"ff02::1 ip6-allnodes\n"
|
||||
"ff02::2 ip6-allrouters\n";
|
||||
const char *loop_ip = "127.0.0.1 ";
|
||||
|
||||
/* 3.generate content for hosts that need to mount */
|
||||
|
||||
if (strlen(container->hostname) > (((SIZE_MAX - strlen(default_config)) - strlen(loop_ip)) - 2)) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
content_len = strlen(default_config) + strlen(loop_ip) + strlen(container->hostname) + 1 + 1;
|
||||
content = util_common_calloc_s(content_len);
|
||||
if (content == NULL) {
|
||||
ERROR("Memory out");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
nret = snprintf(content, content_len, "%s%s%s\n", default_config, loop_ip, container->hostname);
|
||||
if (nret < 0 || (size_t)nret >= content_len) {
|
||||
ERROR("Snprintf failed");
|
||||
goto out_free;
|
||||
}
|
||||
/* 4.get file path for hosts */
|
||||
ret = mount_get_bundle_file(&bundle, c->name, c->config_path, filename);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
/* 5.generate hosts file that need to mount */
|
||||
ret = util_write_file(bundle, content, strlen(content), false, NETWORK_MOUNT_FILE_MODE);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
/* 6.Add one mount nodes to container->mounts */
|
||||
ret = mount_file(container, bundle, filename, targetdir);
|
||||
if (!ret) {
|
||||
ERROR("mount hostname file failed");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(bundle);
|
||||
free(content);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool is_system_container(const oci_runtime_spec *container)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) {
|
||||
if (strcmp(container->annotations->keys[i], "system.container") == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool copy_host_file_to_bundle(const struct lxc_container *c, const char *rootfs, const char *filename)
|
||||
{
|
||||
char *bundle = NULL;
|
||||
char full_path[PATH_MAX] = { 0 };
|
||||
bool ret = true;
|
||||
int nret;
|
||||
|
||||
nret = snprintf(full_path, sizeof(full_path), "%s%s%s", rootfs, "/etc/", filename);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(full_path)) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = mount_get_bundle_file(&bundle, c->name, c->config_path, filename);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
ret = util_copy_file(full_path, bundle, NETWORK_MOUNT_FILE_MODE);
|
||||
if (!ret) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free(bundle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool init_system_container_network(const struct lxc_container *c, const char *rootfs)
|
||||
{
|
||||
if (!copy_host_file_to_bundle(c, rootfs, "hostname")) {
|
||||
ERROR("Failed to copy hostname from rootfs to container bundle");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!copy_host_file_to_bundle(c, rootfs, "hosts")) {
|
||||
ERROR("Failed to copy hosts from rootfs to container bundle");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!copy_host_file_to_bundle(c, rootfs, "resolv.conf")) {
|
||||
ERROR("Failed to copy resolv.conf from rootfs to container bundle");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool is_mount_destination_hosts(const char *destination)
|
||||
{
|
||||
return strcmp(destination, "/etc/hosts") == 0;
|
||||
}
|
||||
|
||||
static inline bool is_mount_destination_resolv(const char *destination)
|
||||
{
|
||||
return strcmp(destination, "/etc/resolv.conf") == 0;
|
||||
}
|
||||
|
||||
static bool init_network_files_mount(oci_runtime_spec *container, const struct lxc_container *c, bool share_host)
|
||||
{
|
||||
bool ret = false;
|
||||
bool has_hosts_mount = false;
|
||||
bool has_resolv_mount = false;
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < container->mounts_len; i++) {
|
||||
if (is_mount_destination_hosts(container->mounts[i]->destination)) {
|
||||
has_hosts_mount = true;
|
||||
}
|
||||
if (is_mount_destination_resolv(container->mounts[i]->destination)) {
|
||||
has_resolv_mount = true;
|
||||
}
|
||||
}
|
||||
ret = true;
|
||||
if (!has_resolv_mount) {
|
||||
const char *default_ipv4_dns = "\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n";
|
||||
// 2. create resolv.conf, hosts files
|
||||
if (!mount_network_file(container, c, "/etc/resolv.conf", default_ipv4_dns)) {
|
||||
ERROR("Mount /etc/resolv.conf failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!has_hosts_mount) {
|
||||
if (share_host && file_exists("/etc/hosts")) {
|
||||
ret = mount_network_file(container, c, "/etc/hosts", NULL);
|
||||
} else {
|
||||
ret = mount_hosts(container, c);
|
||||
}
|
||||
}
|
||||
if (!ret) {
|
||||
ERROR("Mount /etc/hosts failed");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool is_invalid_container(const struct lxc_container *c)
|
||||
{
|
||||
return c == NULL || c->name == NULL || c->config_path == NULL;
|
||||
@ -763,37 +185,6 @@ static inline bool is_annotation_value_host(const char *value)
|
||||
return strcmp(value, "host") == 0;
|
||||
}
|
||||
|
||||
static bool init_network_files(oci_runtime_spec *container, const struct lxc_container *c)
|
||||
{
|
||||
bool share_container = false;
|
||||
bool share_host = false;
|
||||
size_t i = 0;
|
||||
|
||||
if (is_invalid_container(c)) {
|
||||
ERROR("Invalid lxc container");
|
||||
return false;
|
||||
}
|
||||
if (container == NULL || container->hostname == NULL) {
|
||||
return true;
|
||||
}
|
||||
if (is_system_container(container)) {
|
||||
return init_system_container_network(c, container->root->path);
|
||||
}
|
||||
// 1. get network mode
|
||||
for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) {
|
||||
if (is_annotation_key_net_mode(container->annotations->keys[i])) {
|
||||
share_container = strncmp(container->annotations->values[i], "container:", strlen("container:")) == 0;
|
||||
share_host = is_annotation_value_host(container->annotations->values[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (share_container) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return init_network_files_mount(container, c, share_host);
|
||||
}
|
||||
|
||||
static inline bool is_root(const char *path)
|
||||
{
|
||||
return strcmp(path, "/") == 0;
|
||||
@ -879,82 +270,29 @@ out_free:
|
||||
free(path);
|
||||
}
|
||||
|
||||
static int prepare_rootfs(struct lxc_container *c, const char *rootfs, char **container_rootfs)
|
||||
{
|
||||
int ret = 0;
|
||||
struct stat st;
|
||||
|
||||
if (is_root(rootfs)) {
|
||||
DEBUG("Rootfs type: \"/\"");
|
||||
*container_rootfs = util_strdup_s("/");
|
||||
} else if (strncmp(rootfs, "overlayfs:", 10) == 0) {
|
||||
DEBUG("Rootfs type: OverlayFS");
|
||||
*container_rootfs = util_strdup_s(rootfs);
|
||||
} else {
|
||||
ret = stat(rootfs, &st);
|
||||
if (ret == 0 && S_ISBLK(st.st_mode)) {
|
||||
DEBUG("Rootfs type: block device");
|
||||
*container_rootfs = util_strdup_s(rootfs);
|
||||
} else if (ret == 0 && S_ISDIR(st.st_mode)) {
|
||||
*container_rootfs = util_strdup_s(rootfs);
|
||||
} else {
|
||||
ERROR("Not supported rootfs type:%s", rootfs);
|
||||
ret = 1;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct lxc_container *lcr_create_new_container(const char *name, const char *lcrpath)
|
||||
{
|
||||
struct lxc_container *c = NULL;
|
||||
|
||||
c = lxc_container_new(name, lcrpath);
|
||||
if (c == NULL) {
|
||||
ERROR("Failed to new container.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_container_exists(c)) {
|
||||
lxc_container_put(c);
|
||||
ERROR("Container already exists.");
|
||||
lcr_set_error_message(LCR_ERR_RUNTIME, "Runtime error:Container already exists:%s", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!create_container_dir(c)) {
|
||||
lxc_container_put(c);
|
||||
return NULL;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static bool lcr_create_spec(const struct lxc_container *c, const char *real_rootfs, const char *oci_config_data)
|
||||
static bool lcr_create_spec(struct lxc_container *c, oci_runtime_spec *oci_spec)
|
||||
{
|
||||
// Translate oci config
|
||||
DEBUG("Translate oci config...\n");
|
||||
if (!translate_spec(c, oci_config_data, real_rootfs)) {
|
||||
if (!translate_spec(c, oci_spec)) {
|
||||
return false;
|
||||
}
|
||||
DEBUG("Translate oci config... done\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const void *oci_config_data)
|
||||
bool lcr_create(const char *name, const char *lcrpath, void *oci_config)
|
||||
{
|
||||
struct lxc_container *c = NULL;
|
||||
int partial_fd = -1;
|
||||
bool bret = false;
|
||||
char *real_rootfs = NULL; /* the real rootfs used by the container */
|
||||
const char *tmp_path = lcrpath ? lcrpath : LCRPATH;
|
||||
oci_runtime_spec *oci_spec = (oci_runtime_spec *)oci_config;
|
||||
|
||||
clear_error_message(&g_lcr_error);
|
||||
engine_set_log_prefix(name);
|
||||
|
||||
c = lcr_create_new_container(name, tmp_path);
|
||||
c = lxc_container_new(name, tmp_path);
|
||||
if (c == NULL) {
|
||||
engine_free_log_prefix();
|
||||
return false;
|
||||
@ -968,26 +306,17 @@ bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const
|
||||
return false;
|
||||
}
|
||||
|
||||
if (prepare_rootfs(c, rootfs, &real_rootfs)) {
|
||||
ERROR("Failed to prepare rootfs");
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (!lcr_create_spec(c, real_rootfs, oci_config_data)) {
|
||||
if (!lcr_create_spec(c, oci_spec)) {
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
bret = true;
|
||||
out_unlock:
|
||||
free(real_rootfs);
|
||||
if (partial_fd >= 0) {
|
||||
close(partial_fd);
|
||||
remove_partial(c);
|
||||
}
|
||||
if (!bret) {
|
||||
if (!remove_container_dir(c)) {
|
||||
WARN("Unable to clean container directory");
|
||||
}
|
||||
if (!c->destroy(c)) {
|
||||
WARN("Unable to clean lxc resources");
|
||||
}
|
||||
@ -1048,69 +377,6 @@ static bool wait_start_pid(pid_t pid, int rfd, const char *name, const char *pat
|
||||
return false;
|
||||
}
|
||||
|
||||
static int save_container_config_file(const char *rootpath, const char *id, const char *json_data, const char *fname)
|
||||
{
|
||||
int ret = 0;
|
||||
int nret = 0;
|
||||
char filename[PATH_MAX] = { 0 };
|
||||
int fd = -1;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (json_data == NULL || strlen(json_data) == 0) {
|
||||
goto out;
|
||||
}
|
||||
nret = snprintf(filename, sizeof(filename), "%s/%s/%s", rootpath, id, fname);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(filename)) {
|
||||
ERROR("Failed to print string");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (file_exists(filename)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = util_open(filename, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
||||
if (fd == -1) {
|
||||
ERROR("Create file %s failed: %s", filename, strerror(errno));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = util_write_nointr(fd, json_data, strlen(json_data));
|
||||
if (len < 0 || ((size_t)len) != strlen(json_data)) {
|
||||
ERROR("Write file %s failed: %s", filename, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
close(fd);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define START_GENERATE_CONFIG "start_generate_config.json"
|
||||
static int save_start_generate_config_json(const char *rootpath, const struct lcr_start_request *request)
|
||||
{
|
||||
start_generate_config sconf = { 0 };
|
||||
char *jsonstr = NULL;
|
||||
parser_error jerr = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (request->uid == 0 && request->gid == 0 &&
|
||||
(request->additional_gids == NULL || request->additional_gids_len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
sconf.uid = request->uid;
|
||||
sconf.gid = request->gid;
|
||||
sconf.additional_gids = request->additional_gids;
|
||||
sconf.additional_gids_len = request->additional_gids_len;
|
||||
|
||||
jsonstr = start_generate_config_generate_json(&sconf, NULL, &jerr);
|
||||
ret = save_container_config_file(rootpath, request->name, jsonstr, START_GENERATE_CONFIG);
|
||||
|
||||
free(jerr);
|
||||
free(jsonstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool lcr_start(const struct lcr_start_request *request)
|
||||
{
|
||||
int pipefd[2] = { -1, -1 };
|
||||
@ -1137,11 +403,6 @@ bool lcr_start(const struct lcr_start_request *request)
|
||||
ERROR("Failed to create pipe\n");
|
||||
goto out_free;
|
||||
}
|
||||
/* generate start config */
|
||||
if (save_start_generate_config_json(path, request) != 0) {
|
||||
ERROR("Failed to generate start config json file");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid == (pid_t) - 1) {
|
||||
@ -1355,21 +616,6 @@ out:
|
||||
return bret;
|
||||
}
|
||||
|
||||
static bool lcr_check_container_stopped(struct lxc_container *c, const char *name)
|
||||
{
|
||||
if (!is_container_can_control(c)) {
|
||||
ERROR("Insufficent privileges to control");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c->is_running(c)) {
|
||||
ERROR("Container is still running");
|
||||
lcr_set_error_message(LCR_ERR_RUNTIME, "Container is still running:%s", name);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, pid_t pid)
|
||||
{
|
||||
struct lxc_container *c = NULL;
|
||||
@ -1406,7 +652,8 @@ bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (!lcr_check_container_stopped(c, name)) {
|
||||
if (!is_container_can_control(c)) {
|
||||
ERROR("Insufficent privileges to control");
|
||||
bret = false;
|
||||
goto out_put;
|
||||
}
|
||||
@ -1910,7 +1157,7 @@ bool lcr_update(const char *name, const char *lcrpath, const struct lcr_cgroup_r
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
if (!do_update(c, name, tmp_path, cr)) {
|
||||
if (!do_update(c, name, tmp_path, (struct lcr_cgroup_resources *)cr)) {
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
@ -1988,57 +1235,3 @@ out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool translate_spec(const struct lxc_container *c, const char *oci_json_data, const char *container_rootfs)
|
||||
{
|
||||
bool ret = false;
|
||||
struct lcr_list *lcr_conf = NULL;
|
||||
oci_runtime_spec *container = NULL;
|
||||
char *seccomp_conf = NULL;
|
||||
|
||||
INFO("Translate new specification file");
|
||||
if (!container_parse(NULL, oci_json_data, &container)) {
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (!is_system_container(container)) {
|
||||
if (!mount_hostname(container, c)) {
|
||||
goto out_free_conf;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_network_files(container, c)) {
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
lcr_conf = lcr_oci2lcr(c, container_rootfs, container, &seccomp_conf);
|
||||
if (lcr_conf == NULL) {
|
||||
ERROR("Create specific configuration failed");
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (container->hooks != NULL && !lcr_save_ocihooks(c->name, c->config_path, container->hooks)) {
|
||||
ERROR("Failed to save %s", OCIHOOKSFILE);
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (!lcr_save_container(c->name, c->config_path, container)) {
|
||||
ERROR("Failed to save %s", OCICONFIGFILE);
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (!lcr_save_spec(c->name, c->config_path, lcr_conf, seccomp_conf)) {
|
||||
ERROR("Failed to save configuration");
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out_free_conf:
|
||||
free_oci_runtime_spec(container);
|
||||
|
||||
lcr_free_config(lcr_conf);
|
||||
free(lcr_conf);
|
||||
|
||||
free(seccomp_conf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size)
|
||||
* param rootfs : the path of rootfs used for the container
|
||||
* param oci_config_data : json string of oci config data
|
||||
*/
|
||||
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const void *oci_config_data);
|
||||
bool lcr_create(const char *name, const char *lcrpath, void *oci_config);
|
||||
|
||||
/*
|
||||
* Start a container
|
||||
@ -180,11 +180,6 @@ struct lcr_start_request {
|
||||
uint32_t start_timeout;
|
||||
const char *container_pidfile;
|
||||
const char *exit_fifo;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
gid_t *additional_gids;
|
||||
size_t additional_gids_len;
|
||||
};
|
||||
bool lcr_start(const struct lcr_start_request *request);
|
||||
|
||||
@ -290,7 +285,6 @@ void lcr_free_errmsg();
|
||||
|
||||
bool lcr_get_container_pids(const char *name, const char *lcrpath, pid_t **pids, size_t *pids_len);
|
||||
|
||||
bool translate_spec(const struct lxc_container *c, const char *oci_json_data, const char *container_rootfs);
|
||||
bool lcr_resize(const char *name, const char *lcrpath, unsigned int height, unsigned int width);
|
||||
bool lcr_exec_resize(const char *name, const char *lcrpath, const char *suffix, unsigned int height,
|
||||
unsigned int width);
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "log.h"
|
||||
#include "error.h"
|
||||
#include "oci_runtime_spec.h"
|
||||
#include "lcrcontainer_extend.h"
|
||||
|
||||
// Cgroup Item Definition
|
||||
#define CGROUP_BLKIO_WEIGHT "blkio.weight"
|
||||
@ -67,88 +68,20 @@ static inline void add_array_kv(char **array, size_t total, size_t *pos, const c
|
||||
add_array_elem(array, total, pos, v);
|
||||
}
|
||||
|
||||
static int make_sure_linux(oci_runtime_spec *oci_spec)
|
||||
static uint64_t stat_get_ull(struct lxc_container *c, const char *item)
|
||||
{
|
||||
if (oci_spec->linux == NULL) {
|
||||
oci_spec->linux = util_common_calloc_s(sizeof(oci_runtime_config_linux));
|
||||
if (oci_spec->linux == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
char buf[80] = { 0 };
|
||||
int len = 0;
|
||||
uint64_t val = 0;
|
||||
|
||||
static int make_sure_linux_resources(oci_runtime_spec *oci_spec)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = make_sure_linux(oci_spec);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
len = c->get_cgroup_item(c, item, buf, sizeof(buf));
|
||||
if (len <= 0) {
|
||||
DEBUG("unable to read cgroup item %s", item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (oci_spec->linux->resources == NULL) {
|
||||
oci_spec->linux->resources = util_common_calloc_s(sizeof(oci_runtime_config_linux_resources));
|
||||
if (oci_spec->linux->resources == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_sure_linux_resources_blkio(oci_runtime_spec *oci_spec)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = make_sure_linux_resources(oci_spec);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oci_spec->linux->resources->block_io == NULL) {
|
||||
oci_spec->linux->resources->block_io =
|
||||
util_common_calloc_s(sizeof(oci_runtime_config_linux_resources_block_io));
|
||||
if (oci_spec->linux->resources->block_io == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_sure_linux_resources_cpu(oci_runtime_spec *oci_spec)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = make_sure_linux_resources(oci_spec);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oci_spec->linux->resources->cpu == NULL) {
|
||||
oci_spec->linux->resources->cpu = util_common_calloc_s(sizeof(oci_runtime_config_linux_resources_cpu));
|
||||
if (oci_spec->linux->resources->cpu == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_sure_linux_resources_mem(oci_runtime_spec *oci_spec)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = make_sure_linux_resources(oci_spec);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oci_spec->linux->resources->memory == NULL) {
|
||||
oci_spec->linux->resources->memory = util_common_calloc_s(sizeof(oci_runtime_config_linux_resources_memory));
|
||||
if (oci_spec->linux->resources->memory == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
val = strtoull(buf, NULL, 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
static bool update_resources_cpuset_mems(struct lxc_container *c, const struct lcr_cgroup_resources *cr)
|
||||
@ -348,16 +281,39 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool update_resources_mem(struct lxc_container *c, const struct lcr_cgroup_resources *cr)
|
||||
static bool update_resources_mem(struct lxc_container *c, struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (update_resources_memory_limit(c, cr) != 0) {
|
||||
goto err_out;
|
||||
// If the memory update is set to -1 we should also set swap to -1, it means unlimited memory.
|
||||
if (cr->memory_limit == -1) {
|
||||
cr->memory_swap = -1;
|
||||
}
|
||||
|
||||
if (update_resources_memory_swap(c, cr) != 0) {
|
||||
goto err_out;
|
||||
if (cr->memory_limit != 0 && cr->memory_swap != 0) {
|
||||
uint64_t cur_mem_limit = stat_get_ull(c, "memory.limit_in_bytes");
|
||||
if (cr->memory_swap == -1 || cur_mem_limit < cr->memory_swap) {
|
||||
if (update_resources_memory_swap(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
if (update_resources_memory_limit(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
if (update_resources_memory_limit(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
if (update_resources_memory_swap(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (update_resources_memory_limit(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
if (update_resources_memory_swap(c, cr) != 0) {
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (update_resources_memory_reservation(c, cr) != 0) {
|
||||
@ -392,7 +348,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool update_resources(struct lxc_container *c, const struct lcr_cgroup_resources *cr)
|
||||
static bool update_resources(struct lxc_container *c, struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
@ -416,284 +372,9 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool save_container_to_disk(const struct lxc_container *c, const oci_runtime_spec *container)
|
||||
bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool bret = true;
|
||||
char *json_container = NULL;
|
||||
struct parser_context ctr = { 0 };
|
||||
parser_error err = NULL;
|
||||
|
||||
if (c == NULL || container == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ctr.options = OPT_PARSE_STRICT;
|
||||
ctr.stderr = stderr;
|
||||
|
||||
json_container = oci_runtime_spec_generate_json(container, &ctr, &err);
|
||||
if (json_container == NULL) {
|
||||
ERROR("Can not generate json: %s", err);
|
||||
bret = false;
|
||||
goto err_out;
|
||||
}
|
||||
if (!translate_spec(c, json_container, NULL)) {
|
||||
bret = false;
|
||||
goto err_out;
|
||||
}
|
||||
err_out:
|
||||
free(json_container);
|
||||
free(err);
|
||||
return bret;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_cpu_shares(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->cpu_shares != 0) {
|
||||
if (make_sure_linux_resources_cpu(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->cpu->shares = cr->cpu_shares;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_cpu_period(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->cpu_period != 0) {
|
||||
if (make_sure_linux_resources_cpu(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->cpu->period = cr->cpu_period;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_cpu_quota(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->cpu_quota != 0) {
|
||||
if (make_sure_linux_resources_cpu(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->cpu->quota = (int64_t)(cr->cpu_quota);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_cpuset_cpus(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->cpuset_cpus != NULL && strcmp(cr->cpuset_cpus, "") != 0) {
|
||||
if (make_sure_linux_resources_cpu(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
free(c->linux->resources->cpu->cpus);
|
||||
c->linux->resources->cpu->cpus = util_strdup_s(cr->cpuset_cpus);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_cpuset_mems(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->cpuset_mems != NULL && strcmp(cr->cpuset_mems, "") != 0) {
|
||||
if (make_sure_linux_resources_cpu(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
free(c->linux->resources->cpu->mems);
|
||||
c->linux->resources->cpu->mems = util_strdup_s(cr->cpuset_mems);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool merge_cgroup_resources_cpu(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (merge_cgroup_resources_cpu_shares(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_cpu_period(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_cpu_quota(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_cpuset_cpus(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_cpuset_mems(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_mem_limit(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->memory_limit != 0) {
|
||||
if (make_sure_linux_resources_mem(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->memory->limit = (int64_t)(cr->memory_limit);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_mem_reservation(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->memory_reservation != 0) {
|
||||
if (make_sure_linux_resources_mem(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->memory->reservation = (int64_t)(cr->memory_reservation);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_mem_swap(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->memory_swap != 0) {
|
||||
if (make_sure_linux_resources_mem(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->memory->swap = (int64_t)(cr->memory_swap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_kernel_memory_limit(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->kernel_memory_limit != 0) {
|
||||
if (make_sure_linux_resources_mem(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->memory->kernel = (int64_t)(cr->kernel_memory_limit);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool merge_cgroup_resources_mem(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (merge_cgroup_resources_mem_limit(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_mem_reservation(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_mem_swap(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_kernel_memory_limit(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int merge_cgroup_resources_blkio_weight(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
if (cr->blkio_weight != 0) {
|
||||
if (make_sure_linux_resources_blkio(c) != 0) {
|
||||
return -1;
|
||||
}
|
||||
c->linux->resources->block_io->weight = (int)(cr->blkio_weight);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool merge_cgroup_resources(oci_runtime_spec *c, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
if (c == NULL || cr == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (merge_cgroup_resources_blkio_weight(c, cr) != 0) {
|
||||
ret = false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = merge_cgroup_resources_cpu(c, cr);
|
||||
if (!ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = merge_cgroup_resources_mem(c, cr);
|
||||
if (!ret) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr)
|
||||
{
|
||||
int rc = 0;
|
||||
bool bret = false;
|
||||
bool restore = false;
|
||||
char *config_json_file = NULL;
|
||||
oci_runtime_spec *container = NULL;
|
||||
oci_runtime_spec *backupcontainer = NULL;
|
||||
struct parser_context ctr = { OPT_PARSE_STRICT, stderr };
|
||||
parser_error err = NULL;
|
||||
|
||||
rc = asprintf(&config_json_file, "%s/%s/%s", lcrpath, name, OCICONFIGFILE);
|
||||
if (rc < 0) {
|
||||
SYSERROR("Failed to allocated memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
backupcontainer = oci_runtime_spec_parse_file(config_json_file, &ctr, &err);
|
||||
if (backupcontainer == NULL) {
|
||||
ERROR("Can not parse %s: %s", OCICONFIGFILE, err);
|
||||
goto out_free;
|
||||
}
|
||||
container = oci_runtime_spec_parse_file(config_json_file, &ctr, &err);
|
||||
if (container == NULL) {
|
||||
ERROR("Can not parse %s: %s", OCICONFIGFILE, err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (!merge_cgroup_resources(container, cr)) {
|
||||
ERROR("Failed to merge cgroup resources");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (!save_container_to_disk(c, container)) {
|
||||
ERROR("Failed to save config to disk");
|
||||
restore = true;
|
||||
goto restore;
|
||||
}
|
||||
|
||||
// If container is not running, update config file is enough,
|
||||
// resources will be updated when the container is started again.
|
||||
@ -702,24 +383,13 @@ bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, c
|
||||
if (c->is_running(c)) {
|
||||
if (!update_resources(c, cr) && c->is_running(c)) {
|
||||
ERROR("Filed to update cgroup resources");
|
||||
restore = true;
|
||||
goto restore;
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
|
||||
bret = true;
|
||||
|
||||
restore:
|
||||
if (restore && !save_container_to_disk(c, backupcontainer)) {
|
||||
ERROR("Failed to restore");
|
||||
bret = false;
|
||||
}
|
||||
|
||||
out_free:
|
||||
free_oci_runtime_spec(backupcontainer);
|
||||
free_oci_runtime_spec(container);
|
||||
free(config_json_file);
|
||||
free(err);
|
||||
if (bret) {
|
||||
clear_error_message(&g_lcr_error);
|
||||
}
|
||||
@ -830,22 +500,6 @@ err_out:
|
||||
return val;
|
||||
}
|
||||
|
||||
static uint64_t stat_get_ull(struct lxc_container *c, const char *item)
|
||||
{
|
||||
char buf[80] = { 0 };
|
||||
int len = 0;
|
||||
uint64_t val = 0;
|
||||
|
||||
len = c->get_cgroup_item(c, item, buf, sizeof(buf));
|
||||
if (len <= 0) {
|
||||
DEBUG("unable to read cgroup item %s", item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = strtoull(buf, NULL, 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs)
|
||||
{
|
||||
const char *state = NULL;
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr);
|
||||
bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, struct lcr_cgroup_resources *cr);
|
||||
|
||||
void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs);
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "utils.h"
|
||||
#include "log.h"
|
||||
#include "conf.h"
|
||||
#include "oci_runtime_hooks.h"
|
||||
|
||||
static struct lxc_container *lcr_new_container(const char *name, const char *path)
|
||||
{
|
||||
@ -188,29 +189,12 @@ out:
|
||||
return ret ? 0 : -1;
|
||||
}
|
||||
|
||||
static int trans_rootfs_linux(struct lcr_list *lcr_conf, const char *container_rootfs, oci_runtime_spec *container,
|
||||
static int trans_rootfs_linux(struct lcr_list *lcr_conf, oci_runtime_spec *container,
|
||||
char **seccomp)
|
||||
{
|
||||
int ret = -1;
|
||||
struct lcr_list *node = NULL;
|
||||
|
||||
/* merge the rootfs config */
|
||||
if (container_rootfs != NULL) {
|
||||
if (!container->root) {
|
||||
container->root = util_common_calloc_s(sizeof(oci_runtime_spec_root));
|
||||
if (!container->root) {
|
||||
ERROR("Out of memory");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (container->root->path) {
|
||||
free(container->root->path);
|
||||
}
|
||||
|
||||
container->root->path = util_strdup_s(container_rootfs);
|
||||
}
|
||||
|
||||
/* lxc.rootfs
|
||||
* lxc.rootfs.options
|
||||
*/
|
||||
@ -256,7 +240,7 @@ static int trans_hostname_hooks_process_mounts(struct lcr_list *lcr_conf, const
|
||||
* lxc.cap.{drop/keep}
|
||||
* lxc.limit.*
|
||||
* lxc.aa_profile
|
||||
* lxc.se_context
|
||||
* lxc.selinux.context
|
||||
*/
|
||||
node = trans_oci_process(container->process);
|
||||
if (node == NULL) {
|
||||
@ -682,7 +666,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, const char *container_rootfs, oci_runtime_spec *container,
|
||||
struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *container,
|
||||
char **seccomp)
|
||||
{
|
||||
struct lcr_list *lcr_conf = NULL;
|
||||
@ -698,7 +682,7 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, const char *containe
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (trans_rootfs_linux(lcr_conf, container_rootfs, container, seccomp)) {
|
||||
if (trans_rootfs_linux(lcr_conf, container, seccomp)) {
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
@ -896,3 +880,133 @@ out_free:
|
||||
|
||||
return bret;
|
||||
}
|
||||
|
||||
static int lcr_write_file(const char *path, const char *data, size_t len)
|
||||
{
|
||||
char *real_path = NULL;
|
||||
int fd = -1;
|
||||
int ret = -1;
|
||||
|
||||
if (path == NULL || strlen(path) == 0 || data == NULL || len == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (util_ensure_path(&real_path, path) < 0) {
|
||||
ERROR("Failed to ensure path %s", path);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fd = util_open(real_path, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE);
|
||||
if (fd == -1) {
|
||||
ERROR("Create file %s failed", real_path);
|
||||
lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", real_path);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (write(fd, data, len) == -1) {
|
||||
ERROR("write data to %s failed: %s", real_path, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_free:
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
}
|
||||
free(real_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static bool lcr_write_ocihooks(const char *path, const oci_runtime_spec_hooks *hooks)
|
||||
{
|
||||
bool ret = false;
|
||||
struct parser_context ctx = { OPT_PARSE_STRICT, stderr };
|
||||
parser_error err = NULL;
|
||||
|
||||
char *json_hooks = oci_runtime_spec_hooks_generate_json(hooks, &ctx, &err);
|
||||
if (json_hooks == NULL) {
|
||||
ERROR("Failed to generate json: %s", err);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (lcr_write_file(path, json_hooks, strlen(json_hooks)) == -1) {
|
||||
ERROR("write json hooks failed: %s", strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out_free:
|
||||
free(err);
|
||||
free(json_hooks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool lcr_save_ocihooks(const char *name, const char *lcrpath, const oci_runtime_spec_hooks *hooks)
|
||||
{
|
||||
const char *path = lcrpath ? lcrpath : LCRPATH;
|
||||
char ocihook[PATH_MAX] = { 0 };
|
||||
char *bundle = NULL;
|
||||
bool bret = false;
|
||||
int nret = 0;
|
||||
|
||||
if (name == NULL) {
|
||||
ERROR("Missing name");
|
||||
return false;
|
||||
}
|
||||
|
||||
bundle = lcr_get_bundle(path, name);
|
||||
if (bundle == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nret = snprintf(ocihook, sizeof(ocihook), "%s/%s", bundle, OCIHOOKSFILE);
|
||||
if (nret < 0 || (size_t)nret >= sizeof(ocihook)) {
|
||||
ERROR("Failed to print string");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
bret = lcr_write_ocihooks(ocihook, hooks);
|
||||
|
||||
out_free:
|
||||
free(bundle);
|
||||
return bret;
|
||||
}
|
||||
|
||||
bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container)
|
||||
{
|
||||
bool ret = false;
|
||||
struct lcr_list *lcr_conf = NULL;
|
||||
char *seccomp_conf = NULL;
|
||||
|
||||
INFO("Translate new specification file");
|
||||
|
||||
lcr_conf = lcr_oci2lcr(c, container, &seccomp_conf);
|
||||
if (lcr_conf == NULL) {
|
||||
ERROR("Translate configuration failed");
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (container->hooks != NULL && !lcr_save_ocihooks(c->name, c->config_path, container->hooks)) {
|
||||
ERROR("Failed to save %s", OCIHOOKSFILE);
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
if (!lcr_save_spec(c->name, c->config_path, lcr_conf, seccomp_conf)) {
|
||||
ERROR("Failed to save configuration");
|
||||
goto out_free_conf;
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
||||
out_free_conf:
|
||||
lcr_free_config(lcr_conf);
|
||||
free(lcr_conf);
|
||||
|
||||
free(seccomp_conf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -58,15 +58,10 @@ bool container_parse(const char *oci_filename, const char *oci_json_data, oci_ru
|
||||
|
||||
/*
|
||||
* Translate oci specification to lcr configuration.
|
||||
* You should pass oci_filename or oci_spec to this function.
|
||||
* param oci_filename : oci spec filename, in json format
|
||||
* param oci_json_data : json string of oci config data
|
||||
* param new_container : return newest oci_runtime_spec struct
|
||||
* param seccomp : return seccomp parsed from oci spec
|
||||
* You should pass oci_filename or oci_spec to this function.
|
||||
* return: a linked list
|
||||
*/
|
||||
struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, const char *container_rootfs,
|
||||
oci_runtime_spec *new_container,
|
||||
struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *container,
|
||||
char **seccomp);
|
||||
|
||||
/*
|
||||
@ -83,6 +78,7 @@ int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **inf
|
||||
|
||||
char *lcr_get_bundle(const char *lcrpath, const char *name);
|
||||
|
||||
bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
10
src/log.c
10
src/log.c
@ -65,10 +65,10 @@ void engine_free_log_prefix(void)
|
||||
static ssize_t write_nointr(int fd, const void *buf, size_t count);
|
||||
|
||||
static void do_fifo_log(const struct engine_log_object_metadata *metadata, const char *timestamp,
|
||||
const char *msg);
|
||||
const char *msg);
|
||||
|
||||
static void do_stderr_log(const struct engine_log_object_metadata *metadata, const char *timestamp,
|
||||
const char *msg);
|
||||
const char *msg);
|
||||
|
||||
/* engine change str logdriver to enum */
|
||||
static int engine_change_str_logdriver_to_enum(const char *driver)
|
||||
@ -212,7 +212,7 @@ out:
|
||||
}
|
||||
|
||||
static int do_log_by_driver(const struct engine_log_object_metadata *metadata, const char *msg,
|
||||
const char *date_time)
|
||||
const char *date_time)
|
||||
{
|
||||
switch (g_engine_log_driver) {
|
||||
case LOG_DRIVER_STDOUT:
|
||||
@ -314,7 +314,7 @@ static void do_write_log_into_file(int log_fd, char *log_msg, size_t max_len, si
|
||||
|
||||
/* log append logfile */
|
||||
static void do_fifo_log(const struct engine_log_object_metadata *metadata, const char *timestamp,
|
||||
const char *msg)
|
||||
const char *msg)
|
||||
{
|
||||
char log_buffer[ENGINE_LOG_BUFFER_SIZE] = { 0 };
|
||||
int log_fd = -1;
|
||||
@ -353,7 +353,7 @@ static void do_fifo_log(const struct engine_log_object_metadata *metadata, const
|
||||
|
||||
/* log append stderr */
|
||||
static void do_stderr_log(const struct engine_log_object_metadata *metadata, const char *timestamp,
|
||||
const char *msg)
|
||||
const char *msg)
|
||||
{
|
||||
char *tmp_prefix = NULL;
|
||||
if (metadata->level > g_engine_log_level) {
|
||||
|
||||
0
tools/static_check
Normal file → Executable file
0
tools/static_check
Normal file → Executable file
Loading…
x
Reference in New Issue
Block a user