Quoting Stéphane Graber ([email protected]): > This reworks the way lxc-ls works in nesting mode. In the past it'd use > attach_wait's subprocess function to call itself in the container's > namespace, carefully only attaching to the namespaces it needed. > > This works great for system containers but not so much as soon as you > also need to attach to userns. Instead this fix moves all of the > container listing code into a get_containers function (hence the massive > diff, sorry), this function is then called recursively. > > For running containers, the function is called through attach_wait > inside the container's namespace, for stopped container, the function is > simply called recursively with a base path (container's rootfs) in an > attempt to find containers that way. > Communication between the parent lxc-ls and the child lxc-ls is done > through a temporary fd and serialized state using json (similar to what > was done using stdout in the previous implementation). > > As get_global_config_item unfortunately caches the values, there's no > easy way to figure out what the lxcpath should be for a root container > when running as non-root, so just use @LXCPATH@ for now and have > python do the parsing itself. > > As a result, the following things now work as expected: > - listing nested unprivileged containers (root containers inside unpriv) > - listing nested containers when they're not running > - filtering containers in nesting mode (only the first level is filtered) > - copy with invalid config (used to traceback) > > Signed-off-by: Stéphane Graber <[email protected]>
One change below, Acked-by: Serge E. Hallyn <[email protected]> ... > +# List of containers, stored as dictionaries > +def get_containers(fd=None, base="/", root=False): > + containers = [] > + > + paths = [args.lxcpath] > + > + if not root: > + paths.append(get_root_path(base)) > + > + # Generate a unique list of valid paths > + paths = set([os.path.normpath("%s/%s" % (base, path)) for path in paths]) > + > + for path in paths: > + if not os.access(path, os.R_OK): > + continue > + > + for container_name in lxc.list_containers(config_path=path): > + entry = {} > + entry['name'] = container_name > + > + # Apply filter > + if root and args.filter and \ > + not re.match(args.filter, container_name): > + continue > + > + # Return before grabbing the object (non-root) > + if not args.state and not args.fancy and not args.nesting: > + containers.append(entry) > + continue > + > + try: > + container = lxc.Container(container_name, path) > + except: > + print("Invalid container: %s" % conainer_name, > file=sys.stderr) > + pass I think you meant continue here instead of pass? Otherwise you will proceed with a bogus 'container'. > + > + if container.controllable: > + state = container.state > + else: > + state = 'UNKNOWN' > + > + # Filter by status > + if args.state and state not in args.state: > + continue _______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
