diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dce2af..c05169d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/lcr.spec b/lcr.spec index 9216e1e..1ce1b25 100644 --- a/lcr.spec +++ b/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 diff --git a/src/conf.c b/src/conf.c index 2fdffbe..b6b106f 100644 --- a/src/conf.c +++ b/src/conf.c @@ -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) { diff --git a/src/conf.h b/src/conf.h index 056fddd..678e575 100644 --- a/src/conf.h +++ b/src/conf.h @@ -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*/ diff --git a/src/json/schema/src/common_c.py b/src/json/schema/src/common_c.py index 4ccf16b..239440a 100644 --- a/src/json/schema/src/common_c.py +++ b/src/json/schema/src/common_c.py @@ -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 . +# +# 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 diff --git a/src/json/schema/src/common_h.py b/src/json/schema/src/common_h.py index c1a8a8b..8baafbe 100644 --- a/src/json/schema/src/common_h.py +++ b/src/json/schema/src/common_h.py @@ -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 . # +# 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 """ diff --git a/src/json/schema/src/generate.py b/src/json/schema/src/generate.py index 534e07e..698262c 100644 --- a/src/json/schema/src/generate.py +++ b/src/json/schema/src/generate.py @@ -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 . +# +# 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 diff --git a/src/json/schema/src/headers.py b/src/json/schema/src/headers.py index 98116a6..e35d24c 100644 --- a/src/json/schema/src/headers.py +++ b/src/json/schema/src/headers.py @@ -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 . # +# 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 diff --git a/src/json/schema/src/helpers.py b/src/json/schema/src/helpers.py index 92a96c9..cb344c6 100644 --- a/src/json/schema/src/helpers.py +++ b/src/json/schema/src/helpers.py @@ -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 . # +# 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 diff --git a/src/json/schema/src/read_file.c b/src/json/schema/src/read_file.c index bbfff73..08b9059 100644 --- a/src/json/schema/src/read_file.c +++ b/src/json/schema/src/read_file.c @@ -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 diff --git a/src/json/schema/src/read_file.h b/src/json/schema/src/read_file.h index 0bf6a25..4edc585 100644 --- a/src/json/schema/src/read_file.h +++ b/src/json/schema/src/read_file.h @@ -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 diff --git a/src/json/schema/src/sources.py b/src/json/schema/src/sources.py index d4b5393..3b5d9a1 100644 --- a/src/json/schema/src/sources.py +++ b/src/json/schema/src/sources.py @@ -19,6 +19,15 @@ # You should have received a copy of the GNU General Public License # along with libocispec. If not, see . # +# 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 diff --git a/src/lcrcontainer.c b/src/lcrcontainer.c index b849d23..68593b5 100644 --- a/src/lcrcontainer.c +++ b/src/lcrcontainer.c @@ -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; -} diff --git a/src/lcrcontainer.h b/src/lcrcontainer.h index 3f263aa..f747339 100644 --- a/src/lcrcontainer.h +++ b/src/lcrcontainer.h @@ -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); diff --git a/src/lcrcontainer_execute.c b/src/lcrcontainer_execute.c index 288da18..ac808e4 100644 --- a/src/lcrcontainer_execute.c +++ b/src/lcrcontainer_execute.c @@ -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; diff --git a/src/lcrcontainer_execute.h b/src/lcrcontainer_execute.h index 5a0d179..6443e5c 100644 --- a/src/lcrcontainer_execute.h +++ b/src/lcrcontainer_execute.h @@ -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); diff --git a/src/lcrcontainer_extend.c b/src/lcrcontainer_extend.c index bccb31f..53ea668 100644 --- a/src/lcrcontainer_extend.c +++ b/src/lcrcontainer_extend.c @@ -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; +} + diff --git a/src/lcrcontainer_extend.h b/src/lcrcontainer_extend.h index cfe6c19..178bd59 100644 --- a/src/lcrcontainer_extend.h +++ b/src/lcrcontainer_extend.h @@ -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 } diff --git a/src/log.c b/src/log.c index a4204d1..68d3172 100644 --- a/src/log.c +++ b/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) { diff --git a/tools/static_check b/tools/static_check old mode 100644 new mode 100755