[lxc-devel] [PATCH 0/2] lxc_attach and user namespaces

2013-03-03 Thread Christian Seiler
As discussed earlier on this list with Serge, here is my first set of
patches that fixes lxc_attach to user namespaces.

The first patch is bascially Serge's patch v2 with the following changes:

 - use socketpair() instead of pipes because we need two-way
   communication; before we exec() we need to make sure that
   the process was added to cgroups, otherwise this can be
   racy (for example, we execute something that fork()s
   immediately, then that may happen before we return from
   attaching the child to groups - this is now fixed)

 - some minor cleanups

 - a large explanatory comment in the source code about the
   general logic

 - use lxc_cgroup_attach directly, don't use prepare/finish/dispose
   (We don't need them any more if we double-fork()!)

The second patch just gets rid of the unnecessary
prepare/finish/dispose functions for cgroup attaching that were
introduced to avoid a triple-fork in the first place.

A few more patches will follow shortly, especially w.r.t. to UID
and shell handling.

-- Christian

PS: As a side note: I currently get some weird error messages when the
attached process ends:
  /bin/sh: 0: Cannot set tty process group (No such process)
Apprently, upon exit, the shell of the container tries to reset the
controlling terminal to have the process group of its parent process be
the foreground process group. That fails, (because parent pid appears to
be 0 from the inside), so it prints this message. Strangely enough, I
got this message only recently, is this a new feature of the shell
current Ubuntu versions use?

I don't see an easy way to suppress the message btw., so I'm open
to suggestions.


--
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
___
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel


[lxc-devel] [PATCH 2/2] lxc_attach: Clean up cgroup attaching code

2013-03-03 Thread Christian Seiler
Since lxc_attach now works with two fork()s anyway due to user
namespaces, the code for attaching to cgroups can be simplified again.

This patch removes the prepare/finish/dispose functions for attaching
to cgroups and just keeps the lxc_cgroup_attach function.
---
 src/lxc/cgroup.c |  154 ++---
 src/lxc/cgroup.h |3 -
 2 files changed, 18 insertions(+), 139 deletions(-)

diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index 6630d6c..8420e08 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -259,37 +259,12 @@ static int cgroup_enable_clone_children(const char *path)
return ret;
 }
 
-static int lxc_one_cgroup_finish_attach(int fd, pid_t pid)
-{
-   char buf[32];
-   int ret;
-
-   snprintf(buf, 32, "%ld", (long)pid);
-
-   ret = write(fd, buf, strlen(buf));
-   if (ret <= 0) {
-   SYSERROR("failed to write pid '%ld' to fd '%d'", (long)pid, fd);
-   ret = -1;
-   } else {
-   ret = 0;
-   }
-
-   close(fd);
-   return ret;
-}
-
-static int lxc_one_cgroup_dispose_attach(int fd)
-{
-   close(fd);
-   return 0;
-}
-
-static int lxc_one_cgroup_prepare_attach(const char *name,
-struct mntent *mntent)
+static int lxc_one_cgroup_attach(const char *name, struct mntent *mntent, 
pid_t pid)
 {
int fd;
char tasks[MAXPATHLEN], initcgroup[MAXPATHLEN];
char *cgmnt = mntent->mnt_dir;
+   char buf[32];
int flags;
int rc;
 
@@ -310,77 +285,26 @@ static int lxc_one_cgroup_prepare_attach(const char *name,
return -1;
}
 
-   return fd;
-}
-
-static int lxc_one_cgroup_attach(const char *name, struct mntent *mntent, 
pid_t pid)
-{
-   int fd;
-
-   fd = lxc_one_cgroup_prepare_attach(name, mntent);
-   if (fd < 0) {
-   return -1;
-   }
-
-   return lxc_one_cgroup_finish_attach(fd, pid);
-}
-
-int lxc_cgroup_dispose_attach(void *data)
-{
-   int *fds = data;
-   int ret, err;
-
-   if (!fds) {
-   return 0;
-   }
-
-   ret = 0;
-
-   for (; *fds >= 0; fds++) {
-   err = lxc_one_cgroup_dispose_attach(*fds);
-   if (err) {
-   ret = err;
-   }
-   }
-
-   free(data);
-
-   return ret;
-}
-
-int lxc_cgroup_finish_attach(void *data, pid_t pid)
-{
-   int *fds = data;
-   int err;
+   snprintf(buf, 32, "%ld", (long)pid);
 
-   if (!fds) {
-   return 0;
+   rc = write(fd, buf, strlen(buf));
+   if (rc <= 0) {
+   SYSERROR("failed to write pid '%ld' to fd '%d'", (long)pid, fd);
+   rc = -1;
+   } else {
+   rc = 0;
}
 
-   for (; *fds >= 0; fds++) {
-   err = lxc_one_cgroup_finish_attach(*fds, pid);
-   if (err) {
-   /* get rid of the rest of them */
-   lxc_cgroup_dispose_attach(data);
-   return -1;
-   }
-   *fds = -1;
-   }
-
-   free(data);
-
-   return 0;
+   close(fd);
+   return rc;
 }
 
-int lxc_cgroup_prepare_attach(const char *name, void **data)
+int lxc_cgroup_attach(const char *name, pid_t pid)
 {
struct mntent *mntent;
FILE *file = NULL;
-   int err = -1;
int found = 0;
-   int *fds;
-   int i;
-   static const int MAXFDS = 256;
+   int err = 0;
 
file = setmntent(MTAB, "r");
if (!file) {
@@ -388,29 +312,7 @@ int lxc_cgroup_prepare_attach(const char *name, void 
**data)
return -1;
}
 
-   /* create a large enough buffer for all practical
-* use cases
-*/
-   fds = malloc(sizeof(int) * MAXFDS);
-   if (!fds) {
-   err = -1;
-   goto out;
-   }
-   for (i = 0; i < MAXFDS; i++) {
-   fds[i] = -1;
-   }
-
-   err = 0;
-   i = 0;
while ((mntent = getmntent(file))) {
-   if (i >= MAXFDS - 1) {
-   ERROR("too many cgroups to attach to, aborting");
-   lxc_cgroup_dispose_attach(fds);
-   errno = ENOMEM;
-   err = -1;
-   goto out;
-   }
-
DEBUG("checking '%s' (%s)", mntent->mnt_dir, mntent->mnt_type);
 
if (strcmp(mntent->mnt_type, "cgroup"))
@@ -421,42 +323,22 @@ int lxc_cgroup_prepare_attach(const char *name, void 
**data)
INFO("[%d] found cgroup mounted at '%s',opts='%s'",
 ++found, mntent->mnt_dir, mntent->mnt_opts);
 
-   fds[i] = lxc_one_cgroup_prepare_attach(name, mntent);
-   if (fds[i] < 0) {
-   err = fds[i];
-   lxc_cgroup_dispose_attach(fds);
+   err = lxc_one_cgroup_attach(name, mnt

[lxc-devel] [PATCH 1/2] lxc_attach: fix break with user namespaces (v3)

2013-03-03 Thread Christian Seiler
When you clone a new user_ns, the child cannot write to the fds
opened by the parent.  Hnadle this by doing an extra fork.  The
grandparent hangs around and waits for its child to tell it the
pid of of the grandchild, which will be the one attached to the
container.  The grandparent then moves the grandchild into the
right cgroup, then waits for the child who in turn is waiting on
the grandchild to complete.

Secondly, when attaching to a new user namespace, your old uid is
not valid, so you are uid -1.  This patch simply does setid+setuid
to 0 if that is the case.  We probably want to be smarter, but
for now this allows lxc-attach to work.

Signed-off-by: Christian Seiler 
---
 src/lxc/lxc_attach.c |  178 ++
 1 files changed, 150 insertions(+), 28 deletions(-)

diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index e1511ef..1f60266 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "attach.h"
@@ -128,9 +129,9 @@ int main(int argc, char *argv[])
struct passwd *passwd;
struct lxc_proc_context_info *init_ctx;
struct lxc_handler *handler;
-   void *cgroup_data = NULL;
uid_t uid;
char *curdir;
+   int cgroup_ipc_sockets[2];
 
ret = lxc_caps_init();
if (ret)
@@ -157,18 +158,6 @@ int main(int argc, char *argv[])
return -1;
}
 
-   if (!elevated_privileges) {
-   /* we have to do this now since /sys/fs/cgroup may not
-* be available inside the container or we may not have
-* the required permissions anymore
-*/
-   ret = lxc_cgroup_prepare_attach(my_args.name, &cgroup_data);
-   if (ret < 0) {
-   ERROR("failed to prepare attaching to cgroup");
-   return -1;
-   }
-   }
-
curdir = getcwd(NULL, 0);
 
/* determine which namespaces the container was created with
@@ -184,6 +173,106 @@ int main(int argc, char *argv[])
}
}
 
+   /* For the cgroup attaching logic to work in conjunction with pid and 
user namespaces,
+* we need to have the following hierarchy:
+*
+* lxc-attach [process executed externally]
+* | socketpair(cgroup_ipc_sockets)
+* | fork()   -> child
+* |   | setns()
+* |   | fork()-> grandchild
+* |   |   | initialize
+* |   |   | signal parent
+* |   |<--|+
+* |   | signal parent |
+* |<--|-+ |
+* | add to cgroups|   |
+* | signal child >|   |
+* |   | signal child >|
+* | waitpid() | waitpid() | exec()
+* |   |<--| exit()
+* |<--| exit()
+* | exit()
+*
+* The rationale is the following: The first parent is needed because 
after
+* setns() (mount + user namespace) we can't access the cgroup 
filesystem
+* to add the pid to the corresponding cgroup. Therefore, we need to do 
that
+* in a process executed on the host, so that's why we need to fork and 
wait
+* for it to have done some initialization (cgroups may restrict certain
+* operations so we have to do that in the end) and use IPC for 
signaling.
+*
+* Then in the child process we do the setns(). However, a process is 
never
+* really attached to a pid namespace (never changes its pid, doesn't 
appear
+* in the pid namespace /proc), only child processes of that process are
+* truely inside the new pid namespace. That's why we need to fork() 
again
+* after setns() before performing final initializations, then signal 
our
+* parent, which signals the primary process, which does cgroup adding,
+* which then signals to the grandchild that it can exec().
+*/
+   ret = socketpair(PF_LOCAL, SOCK_STREAM, 0, cgroup_ipc_sockets);
+   if (ret < 0) {
+   SYSERROR("could not set up required IPC mechanism for 
attaching");
+   return -1;
+   }
+
+   pid = fork();
+   if (pid < 0) {
+   SYSERROR("failed to create first subprocess");
+   return -1;
+   }
+
+   if (pid) {
+   int status;
+   pid_t grandchild;
+
+   close(cgroup_ipc_sockets[1]);
+
+   gparent_rerea

[lxc-devel] How to mount iscsi target in lxc container?

2013-03-03 Thread cmcc.dylan
Hi, everyone.


 Recently, I'm doing some works about linux container. I choose lxc as the 
hypervisor in the cloud platform - OpenNebula. The basic funtions are done. I 
plan to use iscsi storage as shared storage. Beause i choose ubuntu as the 
container os, i execute command "sudo  apt-get install open-iscsi 
open-iscsi-utils". It's failed unfortunately.
 when i install, it show informations as follows:
 update-rc.d: warning: open-iscsi stop runlevel arguments (0 1 6) do not 
match LSB Default-Stop values (0 6)
* Starting iSCSI initiator service iscsid   [ 
OK ] 
* Setting up iSCSI targets  [ 
OK ]


when i execute iscsi discovery commad, it proves it is ok and shows 
informations as follows:
   ubuntu@lxc:~$ sudo iscsiadm -m discovery -t sendtargets -p 192.168.35.17
   192.168.35.17:3260,1 iqn.2013-02.node2
   However, when i execute iscsi login command, it's failed and show 
informations:
$ sudo iscsiadm -m node --targetname iqn.2013-02.node2 -p 192.168.35.17 
--login
Logging in to [iface: default, target: iqn.2013-02.node2, portal: 
192.168.35.17,3260]
iscsiadm: got read error (0/0), daemon died?
iscsiadm: Could not login to [iface: default, target: iqn.2013-02.node2, 
portal: 192.168.35.17,3260]: 
iscsiadm: initiator reported error (18 - could not communicate to iscsid


   Does lxc support iscsi ?
   
   

--
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb___
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel