iSulad/src/services/execution/execute/execution_create.c
LiFeng e2728aa73e iSulad: internal change
Signed-off-by: LiFeng <lifeng68@huawei.com>
2020-01-06 05:11:01 -05:00

1044 lines
29 KiB
C

/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
* iSulad licensed under the Mulan PSL v1.
* You can use this software according to the terms and conditions of the Mulan PSL v1.
* You may obtain a copy of Mulan PSL v1 at:
* http://license.coscl.org.cn/MulanPSL
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v1 for more details.
* Author: tanyifeng
* Create: 2017-11-22
* Description: provide container create callback function definition
********************************************************************************/
#include "execution_create.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/mount.h>
#include <lcr/lcrcontainer.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <sys/stat.h>
#include <pthread.h>
#include <sys/eventfd.h>
#include <malloc.h>
#include "log.h"
#include "engine.h"
#include "console.h"
#include "lcrd_config.h"
#include "config.h"
#include "specs.h"
#include "verify.h"
#include "containers_store.h"
#include "execution_network.h"
#include "runtime.h"
#include "plugin.h"
#include "image.h"
#include "utils.h"
#include "error.h"
#include "constants.h"
static int create_request_check(const container_create_request *request)
{
int ret = 0;
parser_error err = NULL;
if (request == NULL) {
ERROR("Receive NULL container id");
ret = -1;
goto out;
}
if ((request->rootfs == NULL && request->image == NULL)) {
ERROR("Container image or rootfs error");
ret = -1;
goto out;
}
if (request->image != NULL && !util_valid_image_name(request->image)) {
ERROR("invalid image name %s", request->image);
lcrd_set_error_message("Invalid image name '%s'", request->image);
ret = -1;
goto out;
}
if (request->runtime == NULL) {
ERROR("Receive NULL Request runtime");
ret = -1;
goto out;
}
if (!util_valid_runtime_name(request->runtime)) {
ERROR("Invalid runtime name:%s", request->runtime);
lcrd_set_error_message("Invalid runtime name (%s), only \"lcr\" supported.",
request->runtime);
ret = -1;
goto out;
}
if (request->hostconfig == NULL) {
ERROR("Receive NULL Request hostconfig");
ret = -1;
goto out;
}
if (request->customconfig == NULL) {
ERROR("Receive NULL Request customconfig");
ret = -1;
goto out;
}
out:
free(err);
return ret;
}
static host_config *get_host_spec_from_request(const container_create_request *request)
{
parser_error err = NULL;
host_config *host_spec = NULL;
host_spec = host_config_parse_data(request->hostconfig, NULL, &err);
if (host_spec == NULL) {
ERROR("Failed to parse host config data:%s", err);
}
free(err);
return host_spec;
}
static int merge_external_rootfs_to_host_config(host_config *host_spec, const char *external_rootfs)
{
if (host_spec == NULL) {
return -1;
}
host_spec->external_rootfs = external_rootfs != NULL ? util_strdup_s(external_rootfs) : NULL;
return 0;
}
static host_config *get_host_spec(const container_create_request *request)
{
host_config *host_spec = NULL;
host_spec = get_host_spec_from_request(request);
if (host_spec == NULL) {
return NULL;
}
if (merge_external_rootfs_to_host_config(host_spec, request->rootfs) != 0) {
goto error_out;
}
if (verify_host_config_settings(host_spec, false)) {
ERROR("Failed to verify host config settings");
goto error_out;
}
return host_spec;
error_out:
free_host_config(host_spec);
return NULL;
}
static container_custom_config *get_custom_spec_from_request(const container_create_request *request)
{
parser_error err = NULL;
container_custom_config *custom_spec = container_custom_config_parse_data(request->customconfig, NULL, &err);
if (custom_spec == NULL) {
ERROR("Failed to parse custom config data:%s", err);
}
free(err);
return custom_spec;
}
static int add_default_log_config_to_custom_spec(const char *id, const char *runtime_root,
container_custom_config *custom_config)
{
int ret = 0;
/* generate default log path */
if (custom_config->log_config == NULL) {
custom_config->log_config = util_common_calloc_s(sizeof(container_custom_config_log_config));
if (custom_config->log_config == NULL) {
ERROR("Out of memory");
ret = -1;
goto out;
}
}
if (custom_config->log_config->log_file == NULL) {
char default_path[PATH_MAX] = { 0 };
int nret = snprintf(default_path, PATH_MAX, "%s/%s/console.log", runtime_root, id);
if (nret >= PATH_MAX || nret < 0) {
ERROR("Create default log path for container %s failed", id);
ret = -1;
goto out;
}
custom_config->log_config->log_file = util_strdup_s(default_path);
}
out:
return ret;
}
static container_custom_config *get_custom_spec(const char *id, const char *runtime_root,
const container_create_request *request)
{
container_custom_config *custom_spec = NULL;
custom_spec = get_custom_spec_from_request(request);
if (custom_spec == NULL) {
return NULL;
}
if (add_default_log_config_to_custom_spec(id, runtime_root, custom_spec)) {
goto error_out;
}
return custom_spec;
error_out:
free_container_custom_config(custom_spec);
return NULL;
}
static oci_runtime_spec *merge_config(const char *id, const char *image_type, const char *image_name,
const char *ext_config_image, host_config *host_spec,
container_custom_config *custom_spec,
container_config_v2_common_config *v2_spec, char **real_rootfs)
{
oci_runtime_spec *oci_spec = NULL;
oci_spec = merge_container_config(id, image_type, image_name, ext_config_image, host_spec, custom_spec,
v2_spec, real_rootfs);
if (oci_spec == NULL) {
ERROR("Failed to merge config");
goto error_out;
}
if (merge_global_config(oci_spec) != 0) {
ERROR("Failed to merge global config");
goto error_out;
}
return oci_spec;
error_out:
free_oci_runtime_spec(oci_spec);
return NULL;
}
static int merge_config_for_syscontainer(const container_create_request *request, const host_config *host_spec,
const container_custom_config *custom_spec, const oci_runtime_spec *oci_spec)
{
int ret = 0;
if (!host_spec->system_container || request->rootfs == NULL) {
return 0;
}
if (merge_network(host_spec, request->rootfs, custom_spec->hostname) != 0) {
ERROR("Failed to merge network config");
ret = -1;
goto out;
}
if (append_json_map_string_string(oci_spec->annotations, "rootfs.mount", request->rootfs)) {
ERROR("Realloc annotations failed");
ret = -1;
goto out;
}
out:
return ret;
}
static char *try_generate_id()
{
int i = 0;
int max_time = 10;
char *id = NULL;
char *value = NULL;
id = util_common_calloc_s(sizeof(char) * (CONTAINER_ID_MAX_LEN + 1));
if (id == NULL) {
ERROR("Out of memory");
return NULL;
}
for (i = 0; i < max_time; i++) {
if (util_generate_random_str(id, (size_t)CONTAINER_ID_MAX_LEN)) {
ERROR("Generate id failed");
goto err_out;
}
value = name_index_get(id);
if (value != NULL) {
continue;
} else {
goto out;
}
}
err_out:
free(id);
id = NULL;
out:
return id;
}
static int inspect_image(const char *image, imagetool_image **result)
{
int ret = 0;
im_status_request *request = NULL;
im_status_response *response = NULL;
if (image == NULL) {
ERROR("Empty image name or id");
return -1;
}
request = (im_status_request *)util_common_calloc_s(sizeof(im_status_request));
if (request == NULL) {
ERROR("Out of memory");
return -1;
}
request->image.image = util_strdup_s(image);
if (im_image_status(request, &response) != 0) {
if (response != NULL && response->errmsg != NULL) {
ERROR("failed to inspect inspect image info: %s", response->errmsg);
} else {
ERROR("Failed to call status image");
}
ret = -1;
goto cleanup;
}
if (response->image_info != NULL) {
*result = response->image_info->image;
response->image_info->image = NULL;
}
cleanup:
free_im_status_request(request);
free_im_status_response(response);
return ret;
}
static int conf_get_image_id(const char *image, char **id)
{
int ret = 0;
imagetool_image *ir = NULL;
size_t len = 0;
char *image_id = NULL;
if (image == NULL || strcmp(image, "none") == 0) {
*id = util_strdup_s("none");
return 0;
}
if (inspect_image(image, &ir) != 0) {
ERROR("Failed to inspect image status");
ret = -1;
goto out;
}
if (strlen(ir->id) > SIZE_MAX / sizeof(char) - strlen("sha256:")) {
ERROR("Invalid image id");
ret = -1;
goto out;
}
len = strlen("sha256:") + strlen(ir->id) + 1;
image_id = (char *)util_common_calloc_s(len * sizeof(char));
if (image_id == NULL) {
ERROR("Out of memory");
ret = -1;
goto out;
}
int nret = snprintf(image_id, len, "sha256:%s", ir->id);
if (nret < 0 || (size_t)nret >= len) {
ERROR("Failed to sprintf string");
ret = -1;
goto out;
}
*id = image_id;
image_id = NULL;
out:
free_imagetool_image(ir);
free(image_id);
return ret;
}
static int register_new_container(const char *id, const char *runtime, host_config **host_spec,
container_config_v2_common_config **v2_spec)
{
int ret = -1;
bool registed = false;
char *runtime_root = NULL;
char *runtime_stat = NULL;
char *image_id = NULL;
container_t *cont = NULL;
runtime_root = conf_get_routine_rootdir(runtime);
if (runtime_root == NULL) {
goto out;
}
runtime_stat = conf_get_routine_statedir(runtime);
if (runtime_stat == NULL) {
goto out;
}
if (strcmp((*v2_spec)->image_type, IMAGE_TYPE_OCI) == 0) {
if (conf_get_image_id((*v2_spec)->image, &image_id) != 0) {
goto out;
}
}
cont = container_new(runtime, runtime_root, runtime_stat, image_id, host_spec, v2_spec);
if (cont == NULL) {
ERROR("Failed to create container '%s'", id);
goto out;
}
if (container_to_disk_locking(cont)) {
ERROR("Failed to save container '%s'", id);
goto out;
}
registed = containers_store_add(id, cont);
if (!registed) {
ERROR("Failed to register container '%s'", id);
goto out;
}
ret = 0;
out:
free(runtime_root);
free(runtime_stat);
free(image_id);
if (ret != 0) {
container_unref(cont);
}
return ret;
}
static int maintain_container_id(const container_create_request *request, char **out_id, char **out_name)
{
int ret = 0;
char *id = NULL;
char *name = NULL;
id = try_generate_id();
if (id == NULL) {
ERROR("Failed to generate container ID");
lcrd_set_error_message("Failed to generate container ID");
ret = -1;
goto out;
}
set_log_prefix(id);
if (request->id != NULL) {
name = util_strdup_s(request->id);
} else {
name = util_strdup_s(id);
}
if (!util_valid_container_name(name)) {
ERROR("Invalid container name (%s), only [a-zA-Z0-9][a-zA-Z0-9_.-]+$ are allowed.", name);
lcrd_set_error_message("Invalid container name (%s), only [a-zA-Z0-9][a-zA-Z0-9_.-]+$ are allowed.", name);
ret = -1;
goto out;
}
EVENT("Event: {Object: %s, Type: Creating %s}", id, name);
if (!name_index_add(name, id)) {
ERROR("Name %s is in use", name);
lcrd_set_error_message("Conflict. The name \"%s\" is already in use by container %s. "
"You have to remove (or rename) that container to be able to reuse that name.",
name, name);
ret = -1;
goto out;
}
out:
*out_id = id;
*out_name = name;
return ret;
}
static char *get_runtime_from_request(const container_create_request *request)
{
return strings_to_lower(request->runtime);
}
static void pack_create_response(container_create_response *response, const char *id, uint32_t cc)
{
response->cc = cc;
if (g_lcrd_errmsg != NULL) {
response->errmsg = util_strdup_s(g_lcrd_errmsg);
DAEMON_CLEAR_ERRMSG();
}
if (id != NULL) {
response->id = util_strdup_s(id);
}
}
static int prepare_host_channel(const host_config_host_channel *host_channel, const char *user_remap)
{
unsigned int host_uid = 0;
unsigned int host_gid = 0;
unsigned int size = 0;
if (host_channel == NULL) {
return 0;
}
if (util_dir_exists(host_channel->path_on_host)) {
ERROR("Host path '%s' already exist", host_channel->path_on_host);
return -1;
}
if (util_mkdir_p(host_channel->path_on_host, HOST_PATH_MODE)) {
ERROR("Failed to create host path '%s'.", host_channel->path_on_host);
return -1;
}
if (user_remap != NULL) {
if (util_parse_user_remap(user_remap, &host_uid, &host_gid, &size)) {
ERROR("Failed to split string '%s'.", user_remap);
return -1;
}
if (chown(host_channel->path_on_host, host_uid, host_gid) != 0) {
ERROR("Failed to chown host path '%s'.", host_channel->path_on_host);
return -1;
}
}
return 0;
}
void umount_host_channel(const host_config_host_channel *host_channel)
{
if (host_channel == NULL) {
return;
}
if (detect_mount(host_channel->path_on_host)) {
if (umount2(host_channel->path_on_host, MNT_DETACH)) {
ERROR("Failed to umount the target: %s", host_channel->path_on_host);
}
}
if (util_recursive_rmdir(host_channel->path_on_host, 0)) {
ERROR("Failed to delete host path: %s", host_channel->path_on_host);
}
}
static int generate_merged_oci_config_json(const char *id, oci_runtime_spec *oci_spec,
char **oci_config_data)
{
char *err = NULL;
if (verify_container_settings(oci_spec)) {
ERROR("Failed to verify container settings");
return -1;
}
/* modify oci_spec by plugin. */
if (plugin_event_container_pre_create(id, oci_spec)) {
ERROR("Plugin event pre create failed");
(void)plugin_event_container_post_remove2(id, oci_spec); /* ignore error */
return -1;
}
*oci_config_data = oci_runtime_spec_generate_json(oci_spec, 0, &err);
if (*oci_config_data == NULL) {
ERROR("Failed to generate runtime spec json,erro:%s", err);
free(err);
lcrd_set_error_message("Failed to generate runtime spec json");
return -1;
}
free(err);
return 0;
}
static int create_container_root_dir(const char *id, const char *runtime_root)
{
int ret = 0;
int nret;
char container_root[PATH_MAX] = { 0x00 };
mode_t mask = umask(S_IWOTH);
nret = snprintf(container_root, sizeof(container_root), "%s/%s", runtime_root, id);
if ((size_t)nret >= sizeof(container_root) || nret < 0) {
ret = -1;
goto out;
}
// create container dir
nret = util_mkdir_p(container_root, CONFIG_DIRECTORY_MODE);
if (nret != 0 && errno != EEXIST) {
SYSERROR("Failed to create container path %s", container_root);
ret = -1;
goto out;
}
out:
umask(mask);
return ret;
}
static int delete_container_root_dir(const char *id, const char *runtime_root)
{
int ret = 0;
char container_root[PATH_MAX] = { 0x00 };
ret = snprintf(container_root, sizeof(container_root), "%s/%s", runtime_root, id);
if ((size_t)ret >= sizeof(container_root) || ret < 0) {
ERROR("Failed to sprintf invalid root directory %s/%s", runtime_root, id);
ret = -1;
goto out;
}
ret = util_recursive_rmdir(container_root, 0);
if (ret != 0) {
ERROR("Failed to delete container's state directory %s", container_root);
ret = -1;
goto out;
}
out:
return ret;
}
static container_config_v2_common_config *get_config_v2_spec(const char *id, const char *runtime_root,
const host_config *host_spec)
{
container_config_v2_common_config *v2_spec = NULL;
v2_spec = util_common_calloc_s(sizeof(container_config_v2_common_config));
if (v2_spec == NULL) {
ERROR("Failed to malloc container_config_v2_common_config");
return NULL;
}
/* set network config to v2_spec */
if (init_container_network_confs(id, runtime_root, host_spec, v2_spec) != 0) {
ERROR("Init Network files failed");
goto error_out;
}
return v2_spec;
error_out:
free_container_config_v2_common_config(v2_spec);
return NULL;
}
/* save config v2 */
static int create_v2_config_json(const char *id, const char *runtime_root, container_config_v2_common_config *v2_spec)
{
int ret = 0;
char *json_v2 = NULL;
parser_error err = NULL;
container_config_v2 config_v2 = { 0 };
container_config_v2_state state = { 0 };
config_v2.common_config = v2_spec;
config_v2.state = &state;
json_v2 = container_config_v2_generate_json(&config_v2, NULL, &err);
if (json_v2 == NULL) {
ERROR("Failed to generate container config V2 json string:%s", err ? err : " ");
ret = -1;
goto out;
}
ret = save_config_v2_json(id, runtime_root, json_v2);
if (ret != 0) {
ERROR("Failed to save container config V2 json to file");
ret = -1;
goto out;
}
out:
free(json_v2);
free(err);
return ret;
}
/* save host config */
static int create_host_config_json(const char *id, const char *runtime_root, const host_config *host_spec)
{
int ret = 0;
char *json_host_config = NULL;
parser_error err = NULL;
json_host_config = host_config_generate_json(host_spec, NULL, &err);
if (json_host_config == NULL) {
ERROR("Failed to generate container host config json string:%s", err ? err : " ");
ret = -1;
goto out;
}
ret = save_host_config(id, runtime_root, json_host_config);
if (ret != 0) {
ERROR("Failed to save container host config json to file");
ret = -1;
goto out;
}
out:
free(json_host_config);
free(err);
return ret;
}
static int save_container_config_before_create(const char *id, const char *runtime_root, host_config *host_spec,
container_config_v2_common_config *v2_spec)
{
if (create_v2_config_json(id, runtime_root, v2_spec) != 0) {
return -1;
}
if (create_host_config_json(id, runtime_root, host_spec) != 0) {
return -1;
}
return 0;
}
static host_config_host_channel *dup_host_channel(const host_config_host_channel *channel)
{
host_config_host_channel *dup_channel = NULL;
if (channel == NULL) {
return NULL;
}
dup_channel = (host_config_host_channel *)util_common_calloc_s(sizeof(host_config_host_channel));
if (dup_channel == NULL) {
ERROR("Out of memory");
return NULL;
}
dup_channel->path_on_host = channel->path_on_host != NULL ? util_strdup_s(channel->path_on_host) : NULL;
dup_channel->path_in_container = channel->path_in_container != NULL ?
util_strdup_s(channel->path_in_container) : NULL;
dup_channel->permissions = channel->permissions != NULL ? util_strdup_s(channel->permissions) : NULL;
dup_channel->size = channel->size;
return dup_channel;
}
static int verify_merged_custom_config(const container_custom_config *custom_spec)
{
if (verify_health_check_parameter(custom_spec) != 0) {
return -1;
}
return 0;
}
static int response_allocate_memory(container_create_response **response)
{
if (response == NULL) {
ERROR("Invalid NULL input");
return -1;
}
*response = util_common_calloc_s(sizeof(container_create_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
return 0;
}
static int get_request_container_info(const container_create_request *request, char **id, char **name, uint32_t *cc)
{
if (create_request_check(request) != 0) {
ERROR("Invalid create container request");
*cc = LCRD_ERR_INPUT;
return -1;
}
if (maintain_container_id(request, id, name) != 0) {
*cc = LCRD_ERR_EXEC;
return -1;
}
return 0;
}
static int get_request_image_info(const container_create_request *request, char **image_type,
const char **ext_config_image, const char **image_name)
{
*image_type = im_get_image_type(request->image, request->rootfs);
if (*image_type == NULL) {
return -1;
}
if (request->rootfs != NULL) {
*image_name = request->rootfs;
// Do not use none image because none image has no config.
if (strcmp(request->image, "none") && strcmp(request->image, "none:latest")) {
*ext_config_image = request->image;
}
} else {
*image_name = request->image;
}
// Check if config image exist if provided.
if (*ext_config_image != NULL) {
if (!im_config_image_exist(*ext_config_image)) {
return -1;
}
}
return 0;
}
static int preparate_runtime_environment(const container_create_request *request, const char *id,
char **runtime, char **runtime_root, uint32_t *cc)
{
*runtime = get_runtime_from_request(request);
if (*runtime == NULL) {
*cc = LCRD_ERR_INPUT;
return -1;
}
*runtime_root = conf_get_routine_rootdir(*runtime);
if (*runtime_root == NULL) {
*cc = LCRD_ERR_EXEC;
return -1;
}
if (create_container_root_dir(id, *runtime_root) != 0) {
*cc = LCRD_ERR_EXEC;
return -1;
}
return 0;
}
static int get_basic_spec(const container_create_request *request, const char *id, const char *runtime_root,
host_config **host_spec, container_custom_config **custom_spec)
{
*host_spec = get_host_spec(request);
if (*host_spec == NULL) {
return -1;
}
*custom_spec = get_custom_spec(id, runtime_root, request);
if (*custom_spec == NULL) {
return -1;
}
return 0;
}
static int get_v2_spec(const container_create_request *request, const char *id, const char *name,
const char *runtime_root, const host_config *host_spec, const char *image_type,
container_config_v2_common_config **v2_spec)
{
*v2_spec = get_config_v2_spec(id, runtime_root, host_spec);
if (*v2_spec == NULL) {
ERROR("Failed to malloc container_config_v2_common_config");
return -1;
}
if (v2_spec_make_basic_info(id, name, request->image, image_type, *v2_spec) != 0) {
ERROR("Failed to malloc container_config_v2_common_config");
return -1;
}
return 0;
}
static int v2_spec_merge_config(const container_custom_config *custom_spec, const oci_runtime_spec *oci_spec,
container_config_v2_common_config *v2_spec)
{
if (v2_spec_merge_custom_spec(custom_spec, v2_spec) != 0) {
ERROR("Failed to malloc container_config_v2_common_config");
return -1;
}
if (v2_spec_merge_oci_spec(oci_spec, v2_spec) != 0) {
ERROR("Failed to malloc container_config_v2_common_config");
return -1;
}
return 0;
}
static int generate_oci_config_json(const char *id, const container_create_request *request,
const host_config *host_spec, const container_custom_config *custom_spec,
oci_runtime_spec *oci_spec, char **oci_config_data)
{
if (verify_merged_custom_config(custom_spec)) {
return -1;
}
if (merge_config_for_syscontainer(request, host_spec, custom_spec, oci_spec) != 0) {
ERROR("Failed to merge config for syscontainer");
return -1;
}
if (generate_merged_oci_config_json(id, oci_spec, oci_config_data) != 0) {
return -1;
}
return 0;
}
int container_create_cb(const container_create_request *request,
container_create_response **response)
{
uint32_t cc = LCRD_SUCCESS;
char *real_rootfs = NULL;
char *image_type = NULL;
char *runtime_root = NULL;
char *oci_config_data = NULL;
char *runtime = NULL;
char *name = NULL;
char *id = NULL;
const char *image_name = NULL;
const char *ext_config_image = NULL;
oci_runtime_spec *oci_spec = NULL;
host_config *host_spec = NULL;
container_custom_config *custom_spec = NULL;
container_config_v2_common_config *v2_spec = NULL;
host_config_host_channel *host_channel = NULL;
rt_create_params_t create_params = { 0 };
rt_rm_params_t delete_params = { 0 };
DAEMON_CLEAR_ERRMSG();
if (response_allocate_memory(response) != 0) {
return -1;
}
if (get_request_container_info(request, &id, &name, &cc) != 0) {
goto pack_response;
}
if (get_request_image_info(request, &image_type, &ext_config_image, &image_name) != 0) {
cc = LCRD_ERR_EXEC;
goto clean_nameindex;
}
if (preparate_runtime_environment(request, id, &runtime, &runtime_root, &cc) != 0) {
goto clean_nameindex;
}
if (get_basic_spec(request, id, runtime_root, &host_spec, &custom_spec) != 0) {
cc = LCRD_ERR_INPUT;
goto clean_container_root_dir;
}
if (get_v2_spec(request, id, name, runtime_root, host_spec, image_type, &v2_spec) != 0) {
cc = LCRD_ERR_EXEC;
goto clean_container_root_dir;
}
if (save_container_config_before_create(id, runtime_root, host_spec, v2_spec) != 0) {
cc = LCRD_ERR_EXEC;
goto clean_container_root_dir;
}
host_channel = dup_host_channel(host_spec->host_channel);
if (prepare_host_channel(host_channel, host_spec->user_remap)) {
ERROR("Failed to prepare host channel with '%s'", host_spec->host_channel);
cc = LCRD_ERR_EXEC;
goto clean_container_root_dir;
}
oci_spec = merge_config(id, image_type, image_name, ext_config_image, host_spec, custom_spec, v2_spec,
&real_rootfs);
if (oci_spec == NULL) {
cc = LCRD_ERR_EXEC;
goto clean_rootfs;
}
if (real_rootfs == NULL) {
ERROR("Can not found rootfs");
cc = LCRD_ERR_INPUT;
goto clean_rootfs;
}
if (generate_oci_config_json(id, request, host_spec, custom_spec, oci_spec, &oci_config_data) != 0) {
cc = LCRD_ERR_INPUT;
goto clean_rootfs;
}
create_params.real_rootfs = real_rootfs;
create_params.oci_config_data = oci_config_data;
if (runtime_create(id, runtime, &create_params) != 0) {
ERROR("Runtime create container failed");
cc = LCRD_ERR_EXEC;
goto clean_rootfs;
}
if (v2_spec_merge_config(custom_spec, oci_spec, v2_spec) != 0) {
cc = LCRD_ERR_EXEC;
goto clean_on_error;
}
if (register_new_container(id, runtime, &host_spec, &v2_spec)) {
ERROR("Failed to register new container");
cc = LCRD_ERR_EXEC;
goto clean_on_error;
}
EVENT("Event: {Object: %s, Type: Created %s}", id, name);
goto pack_response;
clean_on_error:
delete_params.rootpath = runtime_root;
(void)runtime_rm(id, runtime, &delete_params);
clean_rootfs:
(void)im_remove_container_rootfs(image_type, id);
umount_host_channel(host_channel);
clean_container_root_dir:
(void)delete_container_root_dir(id, runtime_root);
clean_nameindex:
name_index_remove(name);
pack_response:
pack_create_response(*response, id, cc);
free(runtime);
free(oci_config_data);
free(runtime_root);
free(real_rootfs);
free(image_type);
free(name);
free(id);
free_oci_runtime_spec(oci_spec);
free_host_config(host_spec);
free_container_custom_config(custom_spec);
free_container_config_v2_common_config(v2_spec);
free_host_config_host_channel(host_channel);
free_log_prefix();
malloc_trim(0);
return (cc == LCRD_SUCCESS) ? 0 : -1;
}