[lxc-devel] liblxc, lxc-browse()

Francois-Xavier Bourlet francois-xavier.bourlet at dotcloud.com
Fri May 6 23:53:20 UTC 2011


ok thanks for all the information and example.

I believe that rather than trying to iterate over every containers
running or not and trying to merge the result we could simply iterate
only on running container, or only stopped container (I simplify). So
lxc_for_each could simply take a state in parameter, in case we are
looking for running containers we only have to look in /proc/net/unix
else browsing LXCPATH.

But then what about state like booting/stopping etc? Is
booting/stopping are "running" in some way? Maybe rather than passing
a state to lxc_for_each we can imagine a boolean parameter with the
notion of *active* *inactive*, or something with a better name to
introduce the fact we are looking for "running" container or simply
registered ones?

I have to run really ofter lxc_for_each, and adding complexity (and so
slowing down the function) is a big concern for me. I dont need a full
list of every containers in every state, but only whats is actually
present in the cgroup filesystem and what is registered. I would
prefer to let the user (the developer using lxc_for_each) decide and
implement itself the appropriate complexity.

What do you think?

On Fri, May 6, 2011 at 4:26 PM, Daniel Lezcano <daniel.lezcano at free.fr> wrote:
> On 05/04/2011 08:18 PM, Francois-Xavier Bourlet wrote:
>>
>> Hi,
>>
>> Ok I take note about inline patches in email.
>>
>> - About your version of lxc_for_each, your version is a lots better.
>> My code was totally stupid and non-performant. In fact I based my code
>> on something else that was needed the scandir, i simply copy/pasted by
>> laziness. About the full path, in fact it was used only for the isdir.
>> Again my code was really crappy. Lets start with yours.
>
> ok.
>
>> - About the errno = EINTR inside the for_each, the purpose was to
>> report easily and generically when a callback stop the loop. But
>> honestly, I dont care at all if that's up to the callback to set the
>> errno, since I dont have any use of it in my code. I thought it was
>> more generic and clean, beside that, again, I dont use it myself.
>
> ok.
>
>> Let me explain what I am trying to do, so you can probably drive me to
>> the best solution with your deep understanding of LXC:
>>
>> Since I am implementing some statistics collection for LXC
>> (liblxcstats, https://bitbucket.org/dotcloud/liblxcstats/src). What
>> informations I am retrieving is:
>>
>> - # of registered containers
>> - # of running containers
>> - # of stopped containers
>>
>> At first I wasn't really concerned by counting running containers that
>> are not registered, but hey! nothing prevent me to have more running
>> containers than (registered - stopped) ones in my statistics. It would
>> be more accurate in fact to avoid "forgetting" some running containers
>> because they are not registered I guess.
>
> Yes.
>
>> Maybe the best solution need to create two for_each style functions,
>> one for registered containers, one for running ones? I let you tell me
>> what's the best.
>
> Mmh, not simple at all ...
>
> May be we can have a single lxc_for_each function but pass extra information
> to the callback with the state, created or not.
>
> We should browse first  the LXCPATH directory, for each container get the
> state and call the callback with the container name, the created state and
> the state of the container. Then we store the container name in a hash
> table.
>
> Second loop is to look at /proc/net/unix and look for
> @LXCPATH/<name>/command, get the name from the unix socket name and lookup
> at the hash table. If it is not present, then we have a running container
> which was not created before.
>
> The code to browse the abstract socket for lxc would be something like that:
>
> #include <stdio.h>
> #include <string.h>
> #include <sys/param.h>
>
> #define LXCPATH "/var/lib/lxc"
>
> int main(int argc, char *argv[])
> {
>        const char *file = "/proc/net/unix";
>        const char *format = "%*lx: %*x %*x %*d %*d %*d %*d @LXCPATH/%s";
>        char buffer[MAXPATHLEN];
>        FILE *f;
>        int ret;
>
>        f = fopen(file, "r");
>        if (!f) {
>                perror("fopen '%s' failed");
>                return -1;
>        }
>
>        /* ignore the first line */
>        for (ret = fscanf(f, "%*[^\n]"); ret != EOF; ret = fscanf(f, format,
> buffer)) {
>
>                char *aux;
>
>                /* ignore not matching line */
>                if (!ret) {
>                        ret = fscanf(f, "%*[^\n]");
>                        continue;
>                }
>
>                aux = strchr(buffer, '/');
>                *aux = '\0';
>
>                /* check hash table if the name was already found in the
> created list */
>
>                /* call the callback */
>
>        }
>
>        fclose(f);
>
>        return 0;
> }
>
>
>> Then, for each running containers, I am accessing to the cgroup
>> file-system trough lxc_cgroup_get (to keep everything abstracted as
>> much as possible by lxc) and collect all the statistics I need. So yes
>> I need to browse every running containers, and I guess that even if
>> the container is not registered but running, I can still collect all
>> the statistics.
>>
>> Let me know what do you think!
>
>



-- 
François-Xavier Bourlet




More information about the lxc-devel mailing list