lxc/0138-resize-implement-resize-function-in-exec-start.patch
LiFeng c1c967d9bc lxc: make lxc-libs package
Signed-off-by: LiFeng <lifeng68@huawei.com>
2020-02-14 06:13:22 -05:00

1134 lines
36 KiB
Diff

From 29c845fe630204d35b300241a47ccd4525d315f9 Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Fri, 29 Nov 2019 22:12:10 -0500
Subject: [PATCH 138/139] resize: implement resize function in exec/start
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
src/lxc/Makefile.am | 1 +
src/lxc/attach.c | 45 ++++-
src/lxc/attach.h | 2 +-
src/lxc/commands.c | 44 +++++
src/lxc/commands.h | 9 +
src/lxc/exec_commands.c | 416 +++++++++++++++++++++++++++++++++++++++++++++
src/lxc/exec_commands.h | 73 ++++++++
src/lxc/lxccontainer.c | 64 ++++++-
src/lxc/lxccontainer.h | 15 +-
src/lxc/terminal.c | 26 +++
src/lxc/terminal.h | 1 +
src/lxc/tools/arguments.h | 3 +-
src/lxc/tools/lxc_attach.c | 20 ++-
src/lxc/tools/lxc_copy.c | 2 +-
src/lxc/tools/lxc_ls.c | 2 +-
15 files changed, 698 insertions(+), 25 deletions(-)
create mode 100644 src/lxc/exec_commands.c
create mode 100644 src/lxc/exec_commands.h
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 27240cc..c21eb85 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -101,6 +101,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
cgroups/cgroup_utils.c cgroups/cgroup_utils.h \
compiler.h \
commands.c commands.h \
+ exec_commands.c exec_commands.h \
commands_utils.c commands_utils.h \
conf.c conf.h \
confile.c confile.h \
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 1f14eb4..03a7646 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -64,6 +64,7 @@
#include "syscall_wrappers.h"
#include "terminal.h"
#include "utils.h"
+#include "exec_commands.h"
#if HAVE_SYS_PERSONALITY_H
#include <sys/personality.h>
@@ -1208,7 +1209,7 @@ out:
return ret;
}
-int lxc_attach(const char *name, const char *lxcpath,
+int lxc_attach(const char *name, const char *lxcpath, const char *suffix,
lxc_attach_exec_t exec_function, void *exec_payload,
lxc_attach_options_t *options, pid_t *attached_process, char **err_msg)
{
@@ -1221,6 +1222,10 @@ int lxc_attach(const char *name, const char *lxcpath,
struct lxc_terminal terminal;
struct lxc_conf *conf;
struct attach_clone_payload payload = {0};
+ struct lxc_exec_command_handler exec_command;
+
+ exec_command.maincmd_fd = -1;
+ exec_command.terminal = &terminal;
ret = access("/proc/self/ns", X_OK);
if (ret) {
@@ -1354,6 +1359,10 @@ int lxc_attach(const char *name, const char *lxcpath,
}
terminal.log_fd = options->log_fd;
+ if (suffix != NULL) {
+ exec_command.maincmd_fd = lxc_exec_cmd_init(name, lxcpath, suffix);
+ exec_command.terminal = &terminal;
+ }
} else {
lxc_terminal_init(&terminal);
}
@@ -1394,15 +1403,30 @@ int lxc_attach(const char *name, const char *lxcpath,
ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
if (ret < 0) {
SYSERROR("Could not set up required IPC mechanism for attaching");
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ lxc_terminal_delete(&terminal);
+ lxc_terminal_conf_free(&terminal);
+ if (exec_command.maincmd_fd != -1) {
+ close(exec_command.maincmd_fd);
+ }
+ }
free(cwd);
lxc_proc_put_context_info(init_ctx);
return -1;
}
-
/* isulad: pipdfd for get error message of child or grandchild process. */
if (pipe2(conf->errpipe, O_CLOEXEC) != 0) {
SYSERROR("Failed to init errpipe");
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ lxc_terminal_delete(&terminal);
+ lxc_terminal_conf_free(&terminal);
+ if (exec_command.maincmd_fd != -1) {
+ close(exec_command.maincmd_fd);
+ }
+ }
+ close(ipc_sockets[0]);
+ close(ipc_sockets[1]);
free(cwd);
lxc_proc_put_context_info(init_ctx);
return -1;
@@ -1418,6 +1442,15 @@ int lxc_attach(const char *name, const char *lxcpath,
pid = fork();
if (pid < 0) {
SYSERROR("Failed to create first subprocess");
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ lxc_terminal_delete(&terminal);
+ lxc_terminal_conf_free(&terminal);
+ if (exec_command.maincmd_fd != -1) {
+ close(exec_command.maincmd_fd);
+ }
+ }
+ close(ipc_sockets[0]);
+ close(ipc_sockets[1]);
free(cwd);
lxc_proc_put_context_info(init_ctx);
return -1;
@@ -1474,6 +1507,8 @@ int lxc_attach(const char *name, const char *lxcpath,
if (ret < 0)
goto on_error;
+ (void)lxc_exec_cmd_mainloop_add(&descr, &exec_command);
+
TRACE("Initialized terminal mainloop");
}
@@ -1597,6 +1632,9 @@ int lxc_attach(const char *name, const char *lxcpath,
if (options->attach_flags & LXC_ATTACH_TERMINAL) {
lxc_terminal_delete(&terminal);
lxc_terminal_conf_free(&terminal);
+ if (exec_command.maincmd_fd != -1) {
+ close(exec_command.maincmd_fd);
+ }
}
lxc_proc_put_context_info(init_ctx);
@@ -1615,6 +1653,9 @@ int lxc_attach(const char *name, const char *lxcpath,
lxc_attach_terminal_close_master(&terminal);
lxc_attach_terminal_close_peer(&terminal);
lxc_attach_terminal_close_log(&terminal);
+ if (exec_command.maincmd_fd != -1) {
+ close(exec_command.maincmd_fd);
+ }
}
/* Wait for the parent to have setup cgroups. */
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index e62b98b..8626a8e 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -41,7 +41,7 @@ struct lxc_proc_context_info {
int ns_fd[LXC_NS_MAX];
};
-extern int lxc_attach(const char *name, const char *lxcpath,
+extern int lxc_attach(const char *name, const char *lxcpath, const char *suffix,
lxc_attach_exec_t exec_function, void *exec_payload,
lxc_attach_options_t *options, pid_t *attached_process, char **err_msg);
diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index b70564f..8fd929d 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -97,6 +97,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
[LXC_CMD_CONSOLE_LOG] = "console_log",
[LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
[LXC_CMD_SET_TERMINAL_FIFOS] = "set_terminal_fifos",
+ [LXC_CMD_SET_TERMINAL_WINCH] = "set_terminal_winch",
};
if (cmd >= LXC_CMD_MAX)
@@ -1126,6 +1127,48 @@ static int lxc_cmd_set_terminal_fifos_callback(int fd, struct lxc_cmd_req *req,
}
+int lxc_cmd_set_terminal_winch(const char *name, const char *lxcpath, unsigned int height, unsigned int width)
+{
+ int ret = 0, stopped = 0;
+ struct lxc_cmd_set_terminal_winch_request data = { 0 };
+
+ data.height = height;
+ data.width = width;
+
+ struct lxc_cmd_rr cmd = {
+ .req = {
+ .cmd = LXC_CMD_SET_TERMINAL_WINCH,
+ .datalen = sizeof(struct lxc_cmd_set_terminal_winch_request),
+ .data = &data,
+ },
+ };
+
+ ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
+ if (ret < 0) {
+ ERROR("Failed to send command to container");
+ return -1;
+ }
+
+ if (cmd.rsp.ret != 0) {
+ ERROR("Command response error:%d", cmd.rsp.ret);
+ return -1;
+ }
+ return 0;
+}
+
+static int lxc_cmd_set_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
+ struct lxc_handler *handler)
+{
+ struct lxc_cmd_rsp rsp;
+ struct lxc_cmd_set_terminal_winch_request *data = (struct lxc_cmd_set_terminal_winch_request *)(req->data);
+ memset(&rsp, 0, sizeof(rsp));
+
+ rsp.ret = lxc_set_terminal_winsz(&handler->conf->console, data->height, data->width);;
+
+ return lxc_cmd_rsp_send(fd, &rsp);
+
+}
+
static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
{
@@ -1146,6 +1189,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
[LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
[LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
[LXC_CMD_SET_TERMINAL_FIFOS] = lxc_cmd_set_terminal_fifos_callback,
+ [LXC_CMD_SET_TERMINAL_WINCH] = lxc_cmd_set_terminal_winch_callback,
};
if (req->cmd >= LXC_CMD_MAX) {
diff --git a/src/lxc/commands.h b/src/lxc/commands.h
index 6b64849..c8cc8cd 100644
--- a/src/lxc/commands.h
+++ b/src/lxc/commands.h
@@ -47,6 +47,7 @@ typedef enum {
LXC_CMD_CONSOLE_LOG,
LXC_CMD_SERVE_STATE_CLIENTS,
LXC_CMD_SET_TERMINAL_FIFOS,
+ LXC_CMD_SET_TERMINAL_WINCH,
LXC_CMD_MAX,
} lxc_cmd_t;
@@ -80,6 +81,11 @@ struct lxc_cmd_console_log {
};
+struct lxc_cmd_set_terminal_winch_request {
+ unsigned int height;
+ unsigned int width;
+};
+
extern int lxc_cmd_terminal_winch(const char *name, const char *lxcpath);
extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
const char *lxcpath);
@@ -129,4 +135,7 @@ extern int lxc_cmd_console_log(const char *name, const char *lxcpath,
extern int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath,
const char *in_fifo, const char *out_fifo, const char *err_fifo);
+extern int lxc_cmd_set_terminal_winch(const char *name, const char *lxcpath, unsigned int height, unsigned int width);
+
+
#endif /* __commands_h */
diff --git a/src/lxc/exec_commands.c b/src/lxc/exec_commands.c
new file mode 100644
index 0000000..00129cb
--- /dev/null
+++ b/src/lxc/exec_commands.c
@@ -0,0 +1,416 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
+ * Author: lifeng
+ * Create: 2019-12-08
+ * Description: provide container definition
+ * lxc: linux Container library
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ ******************************************************************************/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <caps.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "af_unix.h"
+#include "cgroup.h"
+#include "exec_commands.h"
+#include "commands_utils.h"
+#include "conf.h"
+#include "config.h"
+#include "confile.h"
+#include "log.h"
+#include "lxc.h"
+#include "lxclock.h"
+#include "mainloop.h"
+#include "monitor.h"
+#include "terminal.h"
+#include "utils.h"
+
+lxc_log_define(commands_exec, lxc);
+
+static const char *lxc_exec_cmd_str(lxc_exec_cmd_t cmd)
+{
+ static const char *const cmdname[LXC_EXEC_CMD_MAX] = {
+ [LXC_EXEC_CMD_SET_TERMINAL_WINCH] = "set_exec_terminal_winch",
+ };
+
+ if (cmd >= LXC_EXEC_CMD_MAX)
+ return "Invalid request";
+
+ return cmdname[cmd];
+}
+
+static int lxc_exec_cmd_rsp_recv(int sock, struct lxc_exec_cmd_rr *cmd)
+{
+ int ret, rspfd;
+ struct lxc_exec_cmd_rsp *rsp = &cmd->rsp;
+
+ ret = lxc_abstract_unix_recv_fds_timeout(sock, &rspfd, 1, rsp, sizeof(*rsp), 1000 * 1000);
+ if (ret < 0) {
+ SYSERROR("Failed to receive response for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+
+ if (errno == ECONNRESET || errno == EAGAIN || errno == EWOULDBLOCK) {
+ errno = ECONNRESET; /*isulad set errno ECONNRESET when timeout */
+ return -1;
+ }
+
+ return -1;
+ }
+ TRACE("Command \"%s\" received response", lxc_exec_cmd_str(cmd->req.cmd));
+
+ if (rsp->datalen == 0) {
+ DEBUG("Response data length for command \"%s\" is 0",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return ret;
+ }
+
+ if (rsp->datalen > LXC_CMD_DATA_MAX) {
+ ERROR("Response data for command \"%s\" is too long: %d bytes > %d",
+ lxc_exec_cmd_str(cmd->req.cmd), rsp->datalen, LXC_CMD_DATA_MAX);
+ return -1;
+ }
+
+ rsp->data = malloc(rsp->datalen);
+ if (!rsp->data) {
+ errno = ENOMEM;
+ ERROR("Failed to allocate response buffer for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
+ if (ret != rsp->datalen) {
+ SYSERROR("Failed to receive response data for command \"%s\"",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ return ret;
+}
+
+static int lxc_exec_cmd_rsp_send(int fd, struct lxc_exec_cmd_rsp *rsp)
+{
+ ssize_t ret;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
+ if (ret < 0 || (size_t)ret != sizeof(*rsp)) {
+ SYSERROR("Failed to send command response %zd", ret);
+ return -1;
+ }
+
+ if (!rsp->data || rsp->datalen <= 0)
+ return 0;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)rsp->datalen) {
+ SYSWARN("Failed to send command response data %zd", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int lxc_exec_cmd_send(const char *name, struct lxc_exec_cmd_rr *cmd,
+ const char *lxcpath, const char *hashed_sock_name, const char *suffix)
+{
+ int client_fd, saved_errno;
+ ssize_t ret = -1;
+
+ client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, suffix);
+ if (client_fd < 0)
+ return -1;
+
+ ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
+ sizeof(cmd->req));
+ if (ret < 0 || (size_t)ret != sizeof(cmd->req))
+ goto on_error;
+
+ if (cmd->req.datalen <= 0)
+ return client_fd;
+
+ errno = EMSGSIZE;
+ ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
+ cmd->req.datalen, MSG_NOSIGNAL);
+ if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
+ goto on_error;
+
+ return client_fd;
+
+on_error:
+ saved_errno = errno;
+ close(client_fd);
+ errno = saved_errno;
+
+ return -1;
+}
+
+static int lxc_exec_cmd(const char *name, struct lxc_exec_cmd_rr *cmd, const char *lxcpath, const char *hashed_sock_name, const char *suffix)
+{
+ int client_fd = -1;
+ int saved_errno;
+ int ret = -1;
+
+ client_fd = lxc_exec_cmd_send(name, cmd, lxcpath, hashed_sock_name, suffix);
+ if (client_fd < 0) {
+ SYSTRACE("Command \"%s\" failed to connect command socket",
+ lxc_exec_cmd_str(cmd->req.cmd));
+ return -1;
+ }
+
+ ret = lxc_exec_cmd_rsp_recv(client_fd, cmd);
+
+ saved_errno = errno;
+ close(client_fd);
+ errno = saved_errno;
+ return ret;
+}
+
+int lxc_exec_cmd_set_terminal_winch(const char *name, const char *lxcpath, const char *suffix, unsigned int height, unsigned int width)
+{
+ int ret = 0;
+ struct lxc_exec_cmd_set_terminal_winch_request data = { 0 };
+
+ data.height = height;
+ data.width = width;
+
+ struct lxc_exec_cmd_rr cmd = {
+ .req = {
+ .cmd = LXC_EXEC_CMD_SET_TERMINAL_WINCH,
+ .datalen = sizeof(struct lxc_exec_cmd_set_terminal_winch_request),
+ .data = &data,
+ },
+ };
+
+ ret = lxc_exec_cmd(name, &cmd, lxcpath, NULL, suffix);
+ if (ret < 0) {
+ ERROR("Failed to send command to container");
+ return -1;
+ }
+
+ if (cmd.rsp.ret != 0) {
+ ERROR("Command response error:%d", cmd.rsp.ret);
+ return -1;
+ }
+ return 0;
+}
+
+static int lxc_exec_cmd_set_terminal_winch_callback(int fd, struct lxc_exec_cmd_req *req,
+ struct lxc_exec_command_handler *handler)
+{
+ struct lxc_exec_cmd_rsp rsp;
+ struct lxc_exec_cmd_set_terminal_winch_request *data = (struct lxc_exec_cmd_set_terminal_winch_request *)(req->data);
+ memset(&rsp, 0, sizeof(rsp));
+
+ rsp.ret = lxc_set_terminal_winsz(handler->terminal, data->height, data->width);;
+
+ return lxc_exec_cmd_rsp_send(fd, &rsp);
+
+}
+
+static int lxc_exec_cmd_process(int fd, struct lxc_exec_cmd_req *req,
+ struct lxc_exec_command_handler *handler)
+{
+ typedef int (*callback)(int, struct lxc_exec_cmd_req *, struct lxc_exec_command_handler *);
+
+ callback cb[LXC_EXEC_CMD_MAX] = {
+ [LXC_EXEC_CMD_SET_TERMINAL_WINCH] = lxc_exec_cmd_set_terminal_winch_callback,
+ };
+
+ if (req->cmd >= LXC_EXEC_CMD_MAX) {
+ ERROR("Undefined command id %d", req->cmd);
+ return -1;
+ }
+ return cb[req->cmd](fd, req, handler);
+}
+
+static void lxc_exec_cmd_fd_cleanup(int fd, struct lxc_epoll_descr *descr)
+{
+ lxc_mainloop_del_handler(descr, fd);
+ close(fd);
+ return;
+}
+
+static int lxc_exec_cmd_handler(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ int ret;
+ struct lxc_exec_cmd_req req;
+ void *reqdata = NULL;
+ struct lxc_exec_command_handler *handler = data;
+
+ ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
+ if (ret < 0) {
+ SYSERROR("Failed to receive data on command socket for command "
+ "\"%s\"", lxc_exec_cmd_str(req.cmd));
+
+ if (errno == EACCES) {
+ /* We don't care for the peer, just send and close. */
+ struct lxc_exec_cmd_rsp rsp = {.ret = ret};
+
+ lxc_exec_cmd_rsp_send(fd, &rsp);
+ }
+
+ goto out_close;
+ }
+
+ if (ret == 0)
+ goto out_close;
+
+ if (ret != sizeof(req)) {
+ WARN("Failed to receive full command request. Ignoring request "
+ "for \"%s\"", lxc_exec_cmd_str(req.cmd));
+ ret = -1;
+ goto out_close;
+ }
+
+ if (req.datalen > LXC_CMD_DATA_MAX) {
+ ERROR("Received command data length %d is too large for "
+ "command \"%s\"", req.datalen, lxc_exec_cmd_str(req.cmd));
+ errno = EFBIG;
+ ret = -EFBIG;
+ goto out_close;
+ }
+
+ if (req.datalen > 0) {
+ reqdata = alloca(req.datalen);
+ if (!reqdata) {
+ ERROR("Failed to allocate memory for \"%s\" command",
+ lxc_exec_cmd_str(req.cmd));
+ errno = ENOMEM;
+ ret = -ENOMEM;
+ goto out_close;
+ }
+
+ ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
+ if (ret != req.datalen) {
+ WARN("Failed to receive full command request. Ignoring "
+ "request for \"%s\"", lxc_exec_cmd_str(req.cmd));
+ ret = LXC_MAINLOOP_ERROR;
+ goto out_close;
+ }
+
+ req.data = reqdata;
+ }
+
+ ret = lxc_exec_cmd_process(fd, &req, handler);
+ if (ret) {
+ /* This is not an error, but only a request to close fd. */
+ ret = LXC_MAINLOOP_CONTINUE;
+ goto out_close;
+ }
+
+out:
+ return ret;
+
+out_close:
+ lxc_exec_cmd_fd_cleanup(fd, descr);
+ goto out;
+}
+
+static int lxc_exec_cmd_accept(int fd, uint32_t events, void *data,
+ struct lxc_epoll_descr *descr)
+{
+ int connection = -1;
+ int opt = 1, ret = -1;
+
+ connection = accept(fd, NULL, 0);
+ if (connection < 0) {
+ SYSERROR("Failed to accept connection to run command");
+ return LXC_MAINLOOP_ERROR;
+ }
+
+ ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ SYSERROR("Failed to set close-on-exec on incoming command connection");
+ goto out_close;
+ }
+
+ ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
+ if (ret < 0) {
+ SYSERROR("Failed to enable necessary credentials on command socket");
+ goto out_close;
+ }
+
+ ret = lxc_mainloop_add_handler(descr, connection, lxc_exec_cmd_handler, data);
+ if (ret) {
+ ERROR("Failed to add command handler");
+ goto out_close;
+ }
+
+out:
+ return ret;
+
+out_close:
+ close(connection);
+ goto out;
+}
+
+int lxc_exec_cmd_init(const char *name, const char *lxcpath, const char *suffix)
+{
+ int fd, ret;
+ char path[LXC_AUDS_ADDR_LEN] = {0};
+
+ ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
+ if (ret < 0)
+ return -1;
+ TRACE("Creating abstract unix socket \"%s\"", &path[1]);
+
+ fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
+ if (fd < 0) {
+ SYSERROR("Failed to create command socket %s", &path[1]);
+ if (errno == EADDRINUSE)
+ ERROR("Container \"%s\" appears to be already running", name);
+
+ return -1;
+ }
+
+ ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret < 0) {
+ SYSERROR("Failed to set FD_CLOEXEC on command socket file descriptor");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+int lxc_exec_cmd_mainloop_add(struct lxc_epoll_descr *descr, struct lxc_exec_command_handler *handler)
+{
+ int ret;
+ int fd = handler->maincmd_fd;
+
+ ret = lxc_mainloop_add_handler(descr, fd, lxc_exec_cmd_accept, handler);
+ if (ret < 0) {
+ ERROR("Failed to add handler for command socket");
+ close(fd);
+ }
+
+ return ret;
+}
diff --git a/src/lxc/exec_commands.h b/src/lxc/exec_commands.h
new file mode 100644
index 0000000..2581ee9
--- /dev/null
+++ b/src/lxc/exec_commands.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
+ * Author: lifeng
+ * Create: 2019-12-08
+ * Description: provide container definition
+ * lxc: linux Container library
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ ******************************************************************************/
+
+#ifndef __LXC_EXEC_COMMANDS_H
+#define __LXC_EXEC_COMMANDS_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "lxccontainer.h"
+#include "macro.h"
+#include "state.h"
+#include "terminal.h"
+
+struct lxc_exec_command_handler {
+ int maincmd_fd;
+ struct lxc_terminal *terminal;
+};
+
+typedef enum {
+ LXC_EXEC_CMD_SET_TERMINAL_WINCH,
+ LXC_EXEC_CMD_MAX,
+} lxc_exec_cmd_t;
+
+struct lxc_exec_cmd_req {
+ lxc_exec_cmd_t cmd;
+ int datalen;
+ const void *data;
+};
+
+struct lxc_exec_cmd_rsp {
+ int ret; /* 0 on success, -errno on failure */
+ int datalen;
+ void *data;
+};
+
+struct lxc_exec_cmd_rr {
+ struct lxc_exec_cmd_req req;
+ struct lxc_exec_cmd_rsp rsp;
+};
+
+struct lxc_exec_cmd_set_terminal_winch_request {
+ unsigned int height;
+ unsigned int width;
+};
+
+struct lxc_epoll_descr;
+struct lxc_handler;
+
+extern int lxc_exec_cmd_init(const char *name, const char *lxcpath, const char *suffix);
+extern int lxc_exec_cmd_mainloop_add(struct lxc_epoll_descr *descr, struct lxc_exec_command_handler *handler);
+extern int lxc_exec_cmd_set_terminal_winch(const char *name, const char *lxcpath, const char *suffix, unsigned int height, unsigned int width);
+
+#endif /* __exec_commands_h */
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 9f9cbfc..7ef57f0 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -47,6 +47,7 @@
#include "cgroup.h"
#include "commands.h"
#include "commands_utils.h"
+#include "exec_commands.h"
#include "conf.h"
#include "config.h"
#include "confile.h"
@@ -4214,7 +4215,7 @@ static bool do_lxcapi_rename(struct lxc_container *c, const char *newname)
WRAP_API_1(bool, lxcapi_rename, const char *)
-static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
+static int lxcapi_attach(struct lxc_container *c, const char *suffix, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
{
int ret;
@@ -4223,12 +4224,12 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio
current_config = c->lxc_conf;
- ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process, &c->lxc_conf->errmsg);
+ ret = lxc_attach(c->name, c->config_path, suffix, exec_function, exec_payload, options, attached_process, &c->lxc_conf->errmsg);
current_config = NULL;
return ret;
}
-static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
+static int do_lxcapi_attach_run_wait(struct lxc_container *c, const char *suffix, lxc_attach_options_t *options, const char *program, const char * const argv[])
{
lxc_attach_command_t command;
pid_t pid;
@@ -4240,7 +4241,7 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options
command.program = (char*)program;
command.argv = (char**)argv;
- r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid, NULL);
+ r = lxc_attach(c->name, c->config_path, suffix, lxc_attach_run_command, &command, options, &pid, NULL);
if (r < 0) {
ERROR("ups");
return r;
@@ -4249,12 +4250,12 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options
return lxc_wait_for_pid_status(pid);
}
-static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
+static int lxcapi_attach_run_wait(struct lxc_container *c, const char *suffix, lxc_attach_options_t *options, const char *program, const char * const argv[])
{
int ret;
current_config = c ? c->lxc_conf : NULL;
- ret = do_lxcapi_attach_run_wait(c, options, program, argv);
+ ret = do_lxcapi_attach_run_wait(c, suffix, options, program, argv);
current_config = NULL;
return ret;
@@ -5109,7 +5110,7 @@ static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool ver
WRAP_API_2(bool, lxcapi_restore, char *, bool)
-static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
+static int lxcapi_attach_run_waitl(struct lxc_container *c, const char *suffix, lxc_attach_options_t *options, const char *program, const char *arg, ...)
{
va_list ap;
const char **argv;
@@ -5131,7 +5132,7 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
}
argv[0] = arg;
- ret = do_lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
+ ret = do_lxcapi_attach_run_wait(c, suffix, options, program, (const char * const *)argv);
free((void*)argv);
out:
@@ -5230,6 +5231,51 @@ static bool do_lxcapi_clean_container_resource(struct lxc_container *c, pid_t pi
WRAP_API_1(bool, lxcapi_clean_container_resource, pid_t)
+static bool do_lxcapi_set_terminal_winch(struct lxc_container *c, unsigned int height, unsigned int width)
+{
+ bool ret = true;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ if (lxc_cmd_set_terminal_winch(c->name, c->config_path, height, width)) {
+ ERROR("Error set terminal winch");
+ ret = false;
+ }
+
+ container_mem_unlock(c);
+ return ret;
+}
+
+WRAP_API_2(bool, lxcapi_set_terminal_winch, unsigned int, unsigned int)
+
+static bool do_lxcapi_set_exec_terminal_winch(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width)
+{
+ bool ret = true;
+
+ if (!c || !c->lxc_conf)
+ return false;
+ if (container_mem_lock(c)) {
+ ERROR("Error getting mem lock");
+ return false;
+ }
+
+ if (lxc_exec_cmd_set_terminal_winch(c->name, c->config_path, suffix, height, width)) {
+ ERROR("Error set terminal winch");
+ ret = false;
+ }
+
+ container_mem_unlock(c);
+ return ret;
+}
+
+WRAP_API_3(bool, lxcapi_set_exec_terminal_winch, const char *, unsigned int, unsigned int)
+
+
/* isulad get coantainer pids */
static bool do_lxcapi_get_container_pids(struct lxc_container *c, pid_t **pids,size_t *pids_len)
{
@@ -5484,6 +5530,8 @@ static struct lxc_container *do_lxc_container_new(const char *name, const char *
c->clean_container_resource = lxcapi_clean_container_resource;
c->add_terminal_fifos = lxcapi_add_terminal_fifo;
c->get_container_pids = lxcapi_get_container_pids;
+ c->set_terminal_winch = lxcapi_set_terminal_winch;
+ c->set_exec_terminal_winch = lxcapi_set_exec_terminal_winch;
/* isulad add end */
return c;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index 608f815..976acf4 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -674,7 +674,7 @@ struct lxc_container {
*
* \return \c 0 on success, \c -1 on error.
*/
- int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function,
+ int (*attach)(struct lxc_container *c, const char *suffix, lxc_attach_exec_t exec_function,
void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process);
/*!
@@ -688,7 +688,7 @@ struct lxc_container {
* \return \c waitpid(2) status of exited process that ran \p
* program, or \c -1 on error.
*/
- int (*attach_run_wait)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[]);
+ int (*attach_run_wait)(struct lxc_container *c, const char *suffix, lxc_attach_options_t *options, const char *program, const char * const argv[]);
/*!
* \brief Run a program inside a container and wait for it to exit (list variant).
@@ -701,7 +701,7 @@ struct lxc_container {
* \return \c waitpid(2) status of exited process that ran \p
* program, or \c -1 on error.
*/
- int (*attach_run_waitl)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...);
+ int (*attach_run_waitl)(struct lxc_container *c, const char *suffix, lxc_attach_options_t *options, const char *program, const char *arg, ...);
/*!
* \brief Create a container snapshot.
@@ -958,6 +958,15 @@ struct lxc_container {
* \return \c true on success, else \c false.
*/
bool (*get_container_pids)(struct lxc_container *c,pid_t **pids,size_t *pids_len);
+ /*! isulad add
+ * \brief An API call to set terminal winch
+ *
+ * \param c Container.
+ * \return \c true on success, else \c false.
+ */
+ bool (*set_terminal_winch)(struct lxc_container *c, unsigned int height, unsigned int width);
+
+ bool (*set_exec_terminal_winch)(struct lxc_container *c, const char *suffix, unsigned int height, unsigned int width);
};
/*!
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index bccc23d..535f374 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -69,6 +69,32 @@ __attribute__((constructor)) void lxc_terminal_init_global(void)
lxc_list_init(&lxc_ttys);
}
+int lxc_set_terminal_winsz(struct lxc_terminal *terminal, unsigned int height, unsigned int width)
+{
+ int ret = 0;
+ struct winsize wsz;
+
+ if (terminal->master < 0) {
+ return 0;
+ }
+
+ ret = ioctl(terminal->master, TIOCGWINSZ, &wsz);
+ if (ret < 0) {
+ WARN("Failed to get window size");
+ return -1;
+ }
+ wsz.ws_col = width;
+ wsz.ws_row = height;
+
+ ret = ioctl(terminal->master, TIOCSWINSZ, &wsz);
+ if (ret < 0)
+ WARN("Failed to set window size");
+ else
+ DEBUG("Set window size to %d columns and %d rows", wsz.ws_col,
+ wsz.ws_row);
+ return ret;
+}
+
void lxc_terminal_winsz(int srcfd, int dstfd)
{
int ret;
diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h
index 9bb341f..4b5c70e 100644
--- a/src/lxc/terminal.h
+++ b/src/lxc/terminal.h
@@ -313,5 +313,6 @@ extern int lxc_terminal_map_ids(struct lxc_conf *c,
/* isulad: if fd == -1, means delete all the fifos*/
int lxc_terminal_delete_fifo(int fd, struct lxc_list *list);
int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames);
+int lxc_set_terminal_winsz(struct lxc_terminal *terminal, unsigned int height, unsigned int width);
#endif /* __LXC_TERMINAL_H */
diff --git a/src/lxc/tools/arguments.h b/src/lxc/tools/arguments.h
index de02aeb..cb7f776 100644
--- a/src/lxc/tools/arguments.h
+++ b/src/lxc/tools/arguments.h
@@ -71,6 +71,7 @@ struct lxc_arguments {
/* for lxc-attach */
int64_t attach_timeout;
+ const char *suffix; /* isulad add, suffix used for connect with parent of execed process*/
/* for lxc-console */
unsigned int ttynum;
@@ -191,7 +192,7 @@ struct lxc_arguments {
#define OPT_DISABLE_PTY OPT_USAGE - 13
#define OPT_OPEN_STDIN OPT_USAGE - 14
#define OPT_ATTACH_TIMEOUT OPT_USAGE - 15
-
+#define OPT_ATTACH_SUFFIX OPT_USAGE - 16
/* isulad add end*/
extern int lxc_arguments_parse(struct lxc_arguments *args, int argc,
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 0d40155..56684e7 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -82,6 +82,7 @@ static const struct option my_longopts[] = {
{"out-fifo", required_argument, 0, OPT_OUTPUT_FIFO},
{"err-fifo", required_argument, 0, OPT_STDERR_FIFO},
{"timeout", required_argument, 0, OPT_ATTACH_TIMEOUT},
+ {"suffix", required_argument, 0, OPT_ATTACH_SUFFIX},
LXC_COMMON_OPTIONS
};
@@ -287,6 +288,9 @@ static int my_parser(struct lxc_arguments *args, int c, char *arg)
}
args->attach_timeout = (unsigned int)atoll(arg);
break;
+ case OPT_ATTACH_SUFFIX:
+ args->suffix = arg;
+ break;
}
return 0;
@@ -351,7 +355,7 @@ static int lxc_attach_create_log_file(const char *log_file)
}
/*isulad: attach with terminal*/
-static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *command,
+static int do_attach_foreground(struct lxc_container *c, const char *suffix, lxc_attach_command_t *command,
lxc_attach_options_t *attach_options,
char **errmsg)
{
@@ -361,9 +365,9 @@ static int do_attach_foreground(struct lxc_container *c, lxc_attach_command_t *c
int signal;
if (command->program)
- ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ ret = c->attach(c, suffix, lxc_attach_run_command, command, attach_options, &pid);
else
- ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
+ ret = c->attach(c, suffix, lxc_attach_run_shell, NULL, attach_options, &pid);
if (ret < 0)
goto out;
@@ -399,7 +403,7 @@ static void close_msg_pipe(int *errpipe)
}
/*isulad: attach without terminal in background */
-static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *command,
+static int do_attach_background(struct lxc_container *c, const char *suffix, lxc_attach_command_t *command,
lxc_attach_options_t *attach_options,
char **errmsg)
{
@@ -458,9 +462,9 @@ static int do_attach_background(struct lxc_container *c, lxc_attach_command_t *c
setsid();
if (command->program)
- ret = c->attach(c, lxc_attach_run_command, command, attach_options, &pid);
+ ret = c->attach(c, suffix, lxc_attach_run_command, command, attach_options, &pid);
else
- ret = c->attach(c, lxc_attach_run_shell, NULL, attach_options, &pid);
+ ret = c->attach(c, suffix, lxc_attach_run_shell, NULL, attach_options, &pid);
if (ret < 0) {
if (c->lxc_conf->errmsg)
lxc_write_error_message(msgpipe[1], "%s", c->lxc_conf->errmsg);
@@ -580,9 +584,9 @@ int main(int argc, char *argv[])
/* isulad: add do attach background */
if (attach_options.attach_flags & LXC_ATTACH_TERMINAL)
- wexit = do_attach_foreground(c, &command, &attach_options, &errmsg);
+ wexit = do_attach_foreground(c, my_args.suffix, &command, &attach_options, &errmsg);
else
- wexit = do_attach_background(c, &command, &attach_options, &errmsg);
+ wexit = do_attach_background(c, my_args.suffix, &command, &attach_options, &errmsg);
if (errmsg) {
fprintf(stderr, "%s:%s:%s:%d starting container process caused \"%s\"", c->name,
diff --git a/src/lxc/tools/lxc_copy.c b/src/lxc/tools/lxc_copy.c
index 954f1dd..b4e2b8f 100644
--- a/src/lxc/tools/lxc_copy.c
+++ b/src/lxc/tools/lxc_copy.c
@@ -467,7 +467,7 @@ static int do_clone_ephemeral(struct lxc_container *c,
goto destroy_and_put;
if (arg->daemonize && arg->argc) {
- ret = clone->attach_run_wait(clone, &attach_options, arg->argv[0], (const char *const *)arg->argv);
+ ret = clone->attach_run_wait(clone, NULL, &attach_options, arg->argv[0], (const char *const *)arg->argv);
if (ret < 0)
goto destroy_and_put;
clone->shutdown(clone, -1);
diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c
index e261c7b..9fd1bf3 100644
--- a/src/lxc/tools/lxc_ls.c
+++ b/src/lxc/tools/lxc_ls.c
@@ -544,7 +544,7 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args,
/* fork(): Attach to the namespace of the container and
* run ls_get() in it which is called in ls_get_wrapper(). */
- check = c->attach(c, ls_get_wrapper, &wargs, &aopt, &out);
+ check = c->attach(c, NULL, ls_get_wrapper, &wargs, &aopt, &out);
/* close the socket */
close(wargs.pipefd[1]);
--
1.8.3.1