Commit 8d06bd13 by Dwight Engen Committed by Serge Hallyn

lxc-monitor multiple paths

parent 566c0d6d
......@@ -63,6 +63,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
to monitor all the containers, several of them or just one.
</para>
<para>
The <option>-P, --lxcpath</option>=PATH option may be specified multiple
times to monitor more than one container path. Note however that
containers with the same name in multiple paths will be
indistinguishable in the output.
</para>
</refsect1>
&commonoptions;
......
......@@ -150,13 +150,32 @@ See the %s man page for further information.\n\n",
exit(code);
}
static int lxc_arguments_lxcpath_add(struct lxc_arguments *args,
const char *lxcpath)
{
if (args->lxcpath_additional != -1 &&
args->lxcpath_cnt > args->lxcpath_additional) {
fprintf(stderr, "This command only accepts %d -P,--lxcpath arguments\n",
args->lxcpath_additional + 1);
exit(EXIT_FAILURE);
}
args->lxcpath = realloc(args->lxcpath, (args->lxcpath_cnt + 1) *
sizeof(args->lxcpath[0]));
if (args->lxcpath == NULL) {
lxc_error(args, "no memory");
return ENOMEM;
}
args->lxcpath[args->lxcpath_cnt++] = lxcpath;
return 0;
}
extern int lxc_arguments_parse(struct lxc_arguments *args,
int argc, char * const argv[])
{
char shortopts[256];
int ret = 0;
args->lxcpath = default_lxc_path();
ret = build_shortopts(args->options, shortopts, sizeof(shortopts));
if (ret < 0) {
lxc_error(args, "build_shortopts() failed : %s",
......@@ -176,7 +195,11 @@ extern int lxc_arguments_parse(struct lxc_arguments *args,
case 'l': args->log_priority = optarg; break;
case 'c': args->console = optarg; break;
case 'q': args->quiet = 1; break;
case 'P': args->lxcpath = optarg; break;
case 'P':
ret = lxc_arguments_lxcpath_add(args, optarg);
if (ret < 0)
return ret;
break;
case OPT_USAGE: print_usage(args->options, args);
case '?': print_help(args, 1);
case 'h': print_help(args, 0);
......@@ -195,6 +218,13 @@ extern int lxc_arguments_parse(struct lxc_arguments *args,
args->argv = &argv[optind];
args->argc = argc - optind;
/* If no lxcpaths were given, use default */
if (!args->lxcpath_cnt) {
ret = lxc_arguments_lxcpath_add(args, default_lxc_path());
if (ret < 0)
return ret;
}
/* Check the command options */
if (!args->name) {
......
......@@ -47,7 +47,10 @@ struct lxc_arguments {
const char *console;
const char *console_log;
const char *pidfile;
const char *lxcpath;
const char **lxcpath;
int lxcpath_cnt;
/* set to 0 to accept only 1 lxcpath, -1 for unlimited */
int lxcpath_additional;
/* for lxc-checkpoint/restart */
const char *statefile;
......
......@@ -28,6 +28,7 @@ extern "C" {
#endif
#include <stddef.h>
#include <sys/types.h>
#include <lxc/state.h>
struct lxc_msg;
......@@ -77,17 +78,37 @@ extern int lxc_execute(const char *name, char *const argv[], int quiet,
extern int lxc_monitor_open(const char *lxcpath);
/*
* Read the state of the container if this one has changed
* The function will block until there is an event available
* @fd : the file descriptor provided by lxc_monitor_open
* @state : the variable which will be filled with the state
* Blocking read for the next container state change
* @fd : the file descriptor provided by lxc_monitor_open
* @msg : the variable which will be filled with the state
* Returns 0 if the monitored container has exited, > 0 if
* data was readen, < 0 otherwise
* data was read, < 0 otherwise
*/
extern int lxc_monitor_read(int fd, struct lxc_msg *msg);
/*
* Blocking read for the next container state change with timeout
* @fd : the file descriptor provided by lxc_monitor_open
* @msg : the variable which will be filled with the state
* @timeout : the timeout in seconds to wait for a state change
* Returns 0 if the monitored container has exited, > 0 if
* data was read, < 0 otherwise
*/
extern int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout);
/*
* Blocking read from multiple monitors for the next container state
* change with timeout
* @rfds : an fd_set of file descriptors provided by lxc_monitor_open
* @nfds : the maximum fd number in rfds + 1
* @msg : the variable which will be filled with the state
* @timeout : the timeout in seconds to wait for a state change
* Returns 0 if the monitored container has exited, > 0 if
* data was read, < 0 otherwise
*/
extern int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg, int timeout);
/*
* Close the fd associated with the monitoring
* @fd : the file descriptor provided by lxc_monitor_open
* Returns 0 on success, < 0 otherwise
......
......@@ -292,11 +292,11 @@ int main(int argc, char *argv[])
return ret;
ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath);
my_args.progname, my_args.quiet, my_args.lxcpath[0]);
if (ret)
return ret;
init_pid = get_init_pid(my_args.name, my_args.lxcpath);
init_pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
if (init_pid < 0) {
ERROR("failed to get the init pid");
return -1;
......@@ -314,7 +314,7 @@ int main(int argc, char *argv[])
* by asking lxc-start
*/
if (namespace_flags == -1) {
namespace_flags = lxc_get_clone_flags(my_args.name, my_args.lxcpath);
namespace_flags = lxc_get_clone_flags(my_args.name, my_args.lxcpath[0]);
/* call failed */
if (namespace_flags == -1) {
ERROR("failed to automatically determine the "
......@@ -387,7 +387,7 @@ int main(int argc, char *argv[])
}
if (!elevated_privileges) {
ret = lxc_cgroup_attach(grandchild, my_args.name, my_args.lxcpath);
ret = lxc_cgroup_attach(grandchild, my_args.name, my_args.lxcpath[0]);
if (ret < 0) {
ERROR("failed to attach process to cgroup");
return -1;
......
......@@ -69,7 +69,7 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
state_object = my_args.argv[0];
......@@ -78,7 +78,7 @@ int main(int argc, char *argv[])
value = my_args.argv[1];
if (value) {
if (lxc_cgroup_set(my_args.name, state_object, value, my_args.lxcpath)) {
if (lxc_cgroup_set(my_args.name, state_object, value, my_args.lxcpath[0])) {
ERROR("failed to assign '%s' value to '%s' for '%s'",
value, state_object, my_args.name);
return -1;
......@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
int ret;
char buffer[len];
ret = lxc_cgroup_get(my_args.name, state_object, buffer, len, my_args.lxcpath);
ret = lxc_cgroup_get(my_args.name, state_object, buffer, len, my_args.lxcpath[0]);
if (ret < 0) {
ERROR("failed to retrieve value of '%s' for '%s'",
state_object, my_args.name);
......
......@@ -116,7 +116,7 @@ int main(int argc, char *argv[])
return ret;
ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath);
my_args.progname, my_args.quiet, my_args.lxcpath[0]);
if (ret)
return ret;
......
......@@ -192,7 +192,7 @@ int main(int argc, char *argv[])
return -1;
err = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath);
my_args.progname, my_args.quiet, my_args.lxcpath[0]);
if (err)
return -1;
......@@ -202,7 +202,7 @@ int main(int argc, char *argv[])
return -1;
}
err = lxc_console(my_args.name, my_args.ttynum, &master, my_args.lxcpath);
err = lxc_console(my_args.name, my_args.ttynum, &master, my_args.lxcpath[0]);
if (err)
goto out;
......
......@@ -101,7 +101,7 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
/* rcfile is specified in the cli option */
......@@ -110,7 +110,7 @@ int main(int argc, char *argv[])
else {
int rc;
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath, my_args.name);
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return -1;
......@@ -137,5 +137,5 @@ int main(int argc, char *argv[])
if (lxc_config_define_load(&defines, conf))
return -1;
return lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath);
return lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath[0]);
}
......@@ -55,9 +55,9 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
return lxc_freeze(my_args.name, my_args.lxcpath);
return lxc_freeze(my_args.name, my_args.lxcpath[0]);
}
......@@ -80,14 +80,14 @@ int main(int argc, char *argv[])
return 1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return 1;
if (!state && !pid)
state = pid = true;
if (state || test_state) {
ret = lxc_getstate(my_args.name, my_args.lxcpath);
ret = lxc_getstate(my_args.name, my_args.lxcpath[0]);
if (ret < 0)
return 1;
if (test_state)
......@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
}
if (pid)
printf("pid:%10d\n", get_init_pid(my_args.name, my_args.lxcpath));
printf("pid:%10d\n", get_init_pid(my_args.name, my_args.lxcpath[0]));
return 0;
}
......@@ -62,7 +62,7 @@ int main(int argc, char *argv[], char *envp[])
return ret;
ret = lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath);
my_args.progname, my_args.quiet, my_args.lxcpath[0]);
if (ret)
return ret;
......@@ -76,7 +76,7 @@ int main(int argc, char *argv[], char *envp[])
} else
sig=SIGKILL;
pid = get_init_pid(my_args.name, my_args.lxcpath);
pid = get_init_pid(my_args.name, my_args.lxcpath[0]);
if (pid < 0) {
ERROR("failed to get the init pid");
return -1;
......
......@@ -52,6 +52,7 @@ Options :\n\
.options = my_longopts,
.parser = NULL,
.checker = NULL,
.lxcpath_additional = -1,
};
int main(int argc, char *argv[])
......@@ -59,14 +60,14 @@ int main(int argc, char *argv[])
char *regexp;
struct lxc_msg msg;
regex_t preg;
int fd;
int len, rc;
fd_set rfds, rfds_save;
int len, rc, i, nfds = -1;
if (lxc_arguments_parse(&my_args, argc, argv))
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
len = strlen(my_args.name) + 3;
......@@ -87,16 +88,33 @@ int main(int argc, char *argv[])
return -1;
}
lxc_monitord_spawn(my_args.lxcpath);
if (my_args.lxcpath_cnt > FD_SETSIZE) {
ERROR("too many paths requested, only the first %d will be monitored", FD_SETSIZE);
my_args.lxcpath_cnt = FD_SETSIZE;
}
fd = lxc_monitor_open(my_args.lxcpath);
if (fd < 0)
return -1;
FD_ZERO(&rfds);
for (i = 0; i < my_args.lxcpath_cnt; i++) {
int fd;
lxc_monitord_spawn(my_args.lxcpath[i]);
fd = lxc_monitor_open(my_args.lxcpath[i]);
if (fd < 0)
return -1;
FD_SET(fd, &rfds);
if (fd > nfds)
nfds = fd;
}
memcpy(&rfds_save, &rfds, sizeof(rfds_save));
nfds++;
setlinebuf(stdout);
for (;;) {
if (lxc_monitor_read(fd, &msg) < 0)
memcpy(&rfds, &rfds_save, sizeof(rfds));
if (lxc_monitor_read_fdset(&rfds, nfds, &msg, -1) < 0)
return -1;
msg.name[sizeof(msg.name)-1] = '\0';
......@@ -118,4 +136,3 @@ int main(int argc, char *argv[])
return 0;
}
......@@ -124,7 +124,7 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
/* rcfile is specified in the cli option */
......@@ -133,7 +133,7 @@ int main(int argc, char *argv[])
else {
int rc;
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath, my_args.name);
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return -1;
......@@ -172,7 +172,7 @@ int main(int argc, char *argv[])
}
}
ret = lxc_restart(my_args.name, sfd, conf, my_args.flags, my_args.lxcpath);
ret = lxc_restart(my_args.name, sfd, conf, my_args.flags, my_args.lxcpath[0]);
if (my_args.statefile)
close(sfd);
......
......@@ -165,7 +165,7 @@ int main(int argc, char *argv[])
args = my_args.argv;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return err;
/* rcfile is specified in the cli option */
......@@ -174,7 +174,7 @@ int main(int argc, char *argv[])
else {
int rc;
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath, my_args.name);
rc = asprintf(&rcfile, "%s/%s/config", my_args.lxcpath[0], my_args.name);
if (rc == -1) {
SYSERROR("failed to allocate memory");
return err;
......@@ -252,7 +252,7 @@ int main(int argc, char *argv[])
if (my_args.close_all_fds)
conf->close_all_fds = 1;
err = lxc_start(my_args.name, args, conf, my_args.lxcpath);
err = lxc_start(my_args.name, args, conf, my_args.lxcpath[0]);
/*
* exec ourself, that requires to have all opened fd
......
......@@ -55,8 +55,8 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
return lxc_stop(my_args.name, my_args.lxcpath);
return lxc_stop(my_args.name, my_args.lxcpath[0]);
}
......@@ -54,9 +54,9 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
return lxc_unfreeze(my_args.name, my_args.lxcpath);
return lxc_unfreeze(my_args.name, my_args.lxcpath[0]);
}
......@@ -84,8 +84,9 @@ int main(int argc, char *argv[])
return -1;
if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet, my_args.lxcpath))
my_args.progname, my_args.quiet, my_args.lxcpath[0]))
return -1;
return lxc_wait(strdup(my_args.name), my_args.states, my_args.timeout, my_args.lxcpath);
return lxc_wait(strdup(my_args.name), my_args.states, my_args.timeout,
my_args.lxcpath[0]);
}
......@@ -147,33 +147,50 @@ err1:
return ret;
}
int lxc_monitor_read_timeout(int fd, struct lxc_msg *msglxc, int timeout)
int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg,
int timeout)
{
fd_set rfds;
struct timeval tv;
int ret;
struct timeval tval,*tv = NULL;
int ret,i;
if (timeout != -1) {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = timeout;
tv.tv_usec = 0;
ret = select(fd+1, &rfds, NULL, NULL, &tv);
if (ret == -1)
return -1;
else if (!ret)
return -2; // timed out
tv = &tval;
tv->tv_sec = timeout;
tv->tv_usec = 0;
}
ret = recv(fd, msglxc, sizeof(*msglxc), 0);
if (ret <= 0) {
SYSERROR("client failed to recv (monitord died?) %s",
strerror(errno));
ret = select(nfds, rfds, NULL, NULL, tv);
if (ret == -1)
return -1;
else if (ret == 0)
return -2; // timed out
/* only read from the first ready fd, the others will remain ready
* for when this routine is called again
*/
for (i = 0; i < nfds; i++) {
if (FD_ISSET(i, rfds)) {
ret = recv(i, msg, sizeof(*msg), 0);
if (ret <= 0) {
SYSERROR("client failed to recv (monitord died?) %s",
strerror(errno));
return -1;
}
return ret;
}
}
return ret;
SYSERROR("no ready fd found?");
return -1;
}
int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout)
{
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
return lxc_monitor_read_fdset(&rfds, fd+1, msg, timeout);
}
int lxc_monitor_read(int fd, struct lxc_msg *msg)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment