mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-09 16:18:52 +00:00
Add attach support to container C API
Signed-off-by: Christian Seiler <christian@iwakd.de> Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
61a1d519f4
commit
a0e93eeb22
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
#include <stdarg.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -38,6 +39,7 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "bdev.h"
|
#include "bdev.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "attach.h"
|
||||||
#include <lxc/utils.h>
|
#include <lxc/utils.h>
|
||||||
#include <lxc/monitor.h>
|
#include <lxc/monitor.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
@ -583,51 +585,30 @@ reboot:
|
|||||||
static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
|
static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char **inargs = NULL, **temp;
|
char **inargs = NULL;
|
||||||
int n_inargs = 0;
|
|
||||||
bool bret = false;
|
bool bret = false;
|
||||||
|
|
||||||
/* container exists */
|
/* container exists */
|
||||||
if (!c)
|
if (!c)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* build array of arguments if any */
|
|
||||||
va_start(ap, useinit);
|
va_start(ap, useinit);
|
||||||
while (1) {
|
inargs = lxc_va_arg_list_to_argv(ap, 0, 1);
|
||||||
char *arg;
|
|
||||||
arg = va_arg(ap, char *);
|
|
||||||
if (!arg)
|
|
||||||
break;
|
|
||||||
n_inargs++;
|
|
||||||
temp = realloc(inargs, n_inargs * sizeof(*inargs));
|
|
||||||
if (!temp) {
|
|
||||||
va_end(ap);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
inargs = temp;
|
|
||||||
inargs[n_inargs - 1] = strdup(arg); // not sure if it's safe not to copy
|
|
||||||
}
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
/* add trailing NULL */
|
if (!inargs) {
|
||||||
if (n_inargs) {
|
ERROR("Memory allocation error.");
|
||||||
n_inargs++;
|
goto out;
|
||||||
temp = realloc(inargs, n_inargs * sizeof(*inargs));
|
|
||||||
if (!temp)
|
|
||||||
goto out;
|
|
||||||
inargs = temp;
|
|
||||||
inargs[n_inargs - 1] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bret = lxcapi_start(c, useinit, inargs);
|
/* pass NULL if no arguments were supplied */
|
||||||
|
bret = lxcapi_start(c, useinit, *inargs ? inargs : NULL);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (inargs) {
|
if (inargs) {
|
||||||
int i;
|
char *arg;
|
||||||
for (i = 0; i < n_inargs; i++) {
|
for (arg = *inargs; arg; arg++)
|
||||||
if (inargs[i])
|
free(arg);
|
||||||
free(inargs[i]);
|
|
||||||
}
|
|
||||||
free(inargs);
|
free(inargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,9 +1114,8 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
|
|||||||
const char *bdevtype, struct bdev_specs *specs, int flags, ...)
|
const char *bdevtype, struct bdev_specs *specs, int flags, ...)
|
||||||
{
|
{
|
||||||
bool bret = false;
|
bool bret = false;
|
||||||
char **args = NULL, **temp;
|
char **args = NULL;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int nargs = 0;
|
|
||||||
|
|
||||||
if (!c)
|
if (!c)
|
||||||
return false;
|
return false;
|
||||||
@ -1145,29 +1125,17 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
|
|||||||
* need to get a copy of the arguments.
|
* need to get a copy of the arguments.
|
||||||
*/
|
*/
|
||||||
va_start(ap, flags);
|
va_start(ap, flags);
|
||||||
while (1) {
|
args = lxc_va_arg_list_to_argv(ap, 0, 0);
|
||||||
char *arg;
|
|
||||||
arg = va_arg(ap, char *);
|
|
||||||
if (!arg)
|
|
||||||
break;
|
|
||||||
nargs++;
|
|
||||||
temp = realloc(args, (nargs+1) * sizeof(*args));
|
|
||||||
if (!temp) {
|
|
||||||
va_end(ap);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
args = temp;
|
|
||||||
args[nargs - 1] = arg;
|
|
||||||
}
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (args)
|
if (!args) {
|
||||||
args[nargs] = NULL;
|
ERROR("Memory allocation error.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
bret = c->create(c, t, bdevtype, specs, flags, args);
|
bret = c->create(c, t, bdevtype, specs, flags, args);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (args)
|
free(args);
|
||||||
free(args);
|
|
||||||
return bret;
|
return bret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2000,6 +1968,57 @@ out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!c)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
|
||||||
|
{
|
||||||
|
lxc_attach_command_t command;
|
||||||
|
pid_t pid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
command.program = (char*)program;
|
||||||
|
command.argv = (char**)argv;
|
||||||
|
r = lxc_attach(c->name, c->config_path, lxc_attach_run_command, &command, options, &pid);
|
||||||
|
if (r < 0) {
|
||||||
|
ERROR("ups");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return lxc_wait_for_pid_status(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
const char **argv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
va_start(ap, arg);
|
||||||
|
argv = lxc_va_arg_list_to_argv_const(ap, 1);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (!argv) {
|
||||||
|
ERROR("Memory allocation error.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
argv[0] = arg;
|
||||||
|
|
||||||
|
ret = lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
|
||||||
|
free((void*)argv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
|
struct lxc_container *lxc_container_new(const char *name, const char *configpath)
|
||||||
{
|
{
|
||||||
struct lxc_container *c;
|
struct lxc_container *c;
|
||||||
@ -2086,6 +2105,9 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
|
|||||||
c->set_config_path = lxcapi_set_config_path;
|
c->set_config_path = lxcapi_set_config_path;
|
||||||
c->clone = lxcapi_clone;
|
c->clone = lxcapi_clone;
|
||||||
c->get_ips = lxcapi_get_ips;
|
c->get_ips = lxcapi_get_ips;
|
||||||
|
c->attach = lxcapi_attach;
|
||||||
|
c->attach_run_wait = lxcapi_attach_run_wait;
|
||||||
|
c->attach_run_waitl = lxcapi_attach_run_waitl;
|
||||||
|
|
||||||
/* we'll allow the caller to update these later */
|
/* we'll allow the caller to update these later */
|
||||||
if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
|
if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef __LXC_CONTAINER_H
|
#ifndef __LXC_CONTAINER_H
|
||||||
#define __LXC_CONTAINER_H
|
#define __LXC_CONTAINER_H
|
||||||
#include "lxclock.h"
|
#include "lxclock.h"
|
||||||
|
#include "attach_options.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
|
|
||||||
@ -150,12 +151,17 @@ struct lxc_container {
|
|||||||
int (*console)(struct lxc_container *c, int ttynum,
|
int (*console)(struct lxc_container *c, int ttynum,
|
||||||
int stdinfd, int stdoutfd, int stderrfd, int escape);
|
int stdinfd, int stdoutfd, int stderrfd, int escape);
|
||||||
|
|
||||||
|
/* create subprocess and attach it to the container, run exec_function inside */
|
||||||
|
int (*attach)(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process);
|
||||||
|
|
||||||
|
/* run program in container, wait for it to exit */
|
||||||
|
int (*attach_run_wait)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[]);
|
||||||
|
int (*attach_run_waitl)(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...);
|
||||||
#if 0
|
#if 0
|
||||||
bool (*commit_cgroups)(struct lxc_container *c);
|
bool (*commit_cgroups)(struct lxc_container *c);
|
||||||
bool (*reread_cgroups)(struct lxc_container *c);
|
bool (*reread_cgroups)(struct lxc_container *c);
|
||||||
// question with clone: how do we handle non-standard config file in orig?
|
// question with clone: how do we handle non-standard config file in orig?
|
||||||
struct lxc_container (*clone)(struct container *c);
|
struct lxc_container (*clone)(struct container *c);
|
||||||
int (*ns_attach)(struct lxc_container *c, int ns_mask);
|
|
||||||
// we'll need some plumbing to support lxc-console
|
// we'll need some plumbing to support lxc-console
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user