[lxc-devel] [PATCH 9/9] lxc-device: rewrite lxc-device.

Dongsheng Yang yangds.fnst at cn.fujitsu.com
Fri Sep 26 02:27:14 UTC 2014


Thanx Hallyn and Graber,
  Sorry for the delay. It is too busy this week. I will address all your 
comments maybe next week.

Thanx
Yang

On 09/20/2014 07:56 AM, Serge Hallyn wrote:
> Quoting Stéphane Graber (stgraber at ubuntu.com):
>> On Fri, Sep 19, 2014 at 09:57:57PM +0000, Serge Hallyn wrote:
>>> Quoting Dongsheng Yang (yangds.fnst at cn.fujitsu.com):
>>>> As there is a function named attach_interface to pass
>>>> a interface to container now, we do not need to relay on
>>>> python impolementation for lxc-device any more.
>>> Don't we still need it for non-network device node?
>> That new lxc_device does that too.
> D'oh.
>
>>>> Signed-off-by: Dongsheng Yang <yangds.fnst at cn.fujitsu.com>
> Thanks, I added a few more notes below, but with all of those
> fixed
>
> Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
>
>>>> ---
>>>>   src/lxc/Makefile.am  |   4 +-
>>>>   src/lxc/lxc-device   |  97 ------------------------------
>>>>   src/lxc/lxc_device.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>>>   3 files changed, 168 insertions(+), 99 deletions(-)
>>>>   delete mode 100644 src/lxc/lxc-device
>>>>   create mode 100644 src/lxc/lxc_device.c
>>>>
>>>> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
>>>> index 8322e62..dab5350 100644
>>>> --- a/src/lxc/Makefile.am
>>>> +++ b/src/lxc/Makefile.am
>>>> @@ -163,14 +163,12 @@ endif
>>>>   bin_SCRIPTS = lxc-checkconfig
>>>>   
>>>>   EXTRA_DIST = \
>>>> -	lxc-device \
>>>>   	lxc-ls \
>>>>   	lxc-top \
>>>>   	lxc.net \
>>>>   	lxc-restore-net
>>>>   
>>>>   if ENABLE_PYTHON
>>>> -bin_SCRIPTS += lxc-device
>>>>   bin_SCRIPTS += lxc-ls
>>>>   bin_SCRIPTS += lxc-start-ephemeral
>>>>   else
>>>> @@ -191,6 +189,7 @@ bin_PROGRAMS = \
>>>>   	lxc-console \
>>>>   	lxc-create \
>>>>   	lxc-destroy \
>>>> +	lxc-device \
>>>>   	lxc-execute \
>>>>   	lxc-freeze \
>>>>   	lxc-info \
>>>> @@ -222,6 +221,7 @@ lxc_cgroup_SOURCES = lxc_cgroup.c
>>>>   lxc_config_SOURCES = lxc_config.c
>>>>   lxc_console_SOURCES = lxc_console.c
>>>>   lxc_destroy_SOURCES = lxc_destroy.c
>>>> +lxc_device_SOURCES = lxc_device.c
>>>>   lxc_execute_SOURCES = lxc_execute.c
>>>>   lxc_freeze_SOURCES = lxc_freeze.c
>>>>   lxc_info_SOURCES = lxc_info.c
>>>> diff --git a/src/lxc/lxc-device b/src/lxc/lxc-device
>>>> deleted file mode 100644
>>>> index dca161e..0000000
>>>> --- a/src/lxc/lxc-device
>>>> +++ /dev/null
>>>> @@ -1,97 +0,0 @@
>>>> -#!/usr/bin/python3
>>>> -#
>>>> -# lxc-device: Add devices to a running container
>>>> -#
>>>> -# This python implementation is based on the work done in the original
>>>> -# shell implementation done by Serge Hallyn in Ubuntu (and other contributors)
>>>> -#
>>>> -# (C) Copyright Canonical Ltd. 2012
>>>> -#
>>>> -# Authors:
>>>> -# Stéphane Graber <stgraber at ubuntu.com>
>>>> -#
>>>> -# This library is free software; you can redistribute it and/or
>>>> -# modify it under the terms of the GNU Lesser General Public
>>>> -# License as published by the Free Software Foundation; either
>>>> -# version 2.1 of the License, or (at your option) any later version.
>>>> -#
>>>> -# This library is distributed in the hope that it will be useful,
>>>> -# but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> -# Lesser General Public License for more details.
>>>> -#
>>>> -# You should have received a copy of the GNU Lesser General Public
>>>> -# License along with this library; if not, write to the Free Software
>>>> -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>>>> -#
>>>> -
>>>> -import argparse
>>>> -import gettext
>>>> -import lxc
>>>> -import os
>>>> -
>>>> -_ = gettext.gettext
>>>> -gettext.textdomain("lxc-device")
>>>> -
>>>> -# Begin parsing the command line
>>>> -parser = argparse.ArgumentParser(description=_("LXC: Manage devices"),
>>>> -                                 formatter_class=argparse.RawTextHelpFormatter)
>>>> -
>>>> -# Global arguments
>>>> -parser.add_argument("-n", dest="container", metavar="CONTAINER",
>>>> -                    help=_("Name of the container to add the device to"),
>>>> -                    required=True)
>>>> -
>>>> -parser.add_argument("-P", "--lxcpath", dest="lxcpath", metavar="PATH",
>>>> -                    help=_("Use specified container path"), default=None)
>>>> -
>>>> -parser.add_argument("--version", action="version", version=lxc.version)
>>>> -
>>>> -# Commands
>>>> -subparsers = parser.add_subparsers()
>>>> -subparser_add = subparsers.add_parser('add', help=_('Add a device'))
>>>> -subparser_add.set_defaults(action="add")
>>>> -
>>>> -subparser_add.add_argument(dest="device", metavar="DEVICE",
>>>> -                           help=_("Add a device "
>>>> -                                  "(path to a node or interface name)"))
>>>> -
>>>> -subparser_add.add_argument(dest="name", metavar="NAME", nargs="?",
>>>> -                           help=_("Use an alternative path or name "
>>>> -                                  "in the container"))
>>>> -
>>>> -args = parser.parse_args()
>>>> -
>>>> -# Some basic checks
>>>> -## Check for valid action
>>>> -if not hasattr(args, "action"):
>>>> -    parser.error(_("You must specify an action."))
>>>> -
>>>> -## Don't rename if no alternative name
>>>> -if not args.name:
>>>> -    args.name = args.device
>>>> -
>>>> -## Check that the container is ready
>>>> -container = lxc.Container(args.container, args.lxcpath)
>>>> -
>>>> -## Check that we have control over the container
>>>> -if not container.controllable:
>>>> -    parser.error("Insufficent privileges to control: %s" % container.name)
>>>> -
>>>> -## Check that the container is running
>>>> -if not container.running:
>>>> -    parser.error("The container must be running.")
>>>> -
>>>> -# Do the work
>>>> -if args.action == "add":
>>>> -    if os.path.exists("/sys/class/net/%s/" % args.device):
>>>> -        ret = container.add_device_net(args.device, args.name)
>>>> -    else:
>>>> -        ret = container.add_device_node(args.device, args.name)
>>>> -
>>>> -    if ret:
>>>> -        print("Added '%s' to '%s' as '%s'." %
>>>> -              (args.device, container.name, args.name))
>>>> -    else:
>>>> -        print("Failed to add '%s' to '%s' as '%s'." %
>>>> -              (args.device, container.name, args.name))
>>>> diff --git a/src/lxc/lxc_device.c b/src/lxc/lxc_device.c
>>>> new file mode 100644
>>>> index 0000000..963f934
>>>> --- /dev/null
>>>> +++ b/src/lxc/lxc_device.c
>>>> @@ -0,0 +1,166 @@
>>>> +/*
>>>> + * lxc: linux Container library
>>>> + *
>>>> + * Authors:
>>>> + * Dongsheng Yang <yangds.fnst at cn.fujitsu.com>
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2.1 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, write to the Free Software
>>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>>>> + */
>>>> +#include <stdio.h>
>>>> +#include <unistd.h>
>>>> +#include <sys/types.h>
>>>> +#include <libgen.h>
>>>> +#include <string.h>
>>>> +#include <limits.h>
>>>> +
>>>> +#include <lxc/lxccontainer.h>
>>>> +
>>>> +#include "utils.h"
>>>> +#include "lxc.h"
>>>> +#include "log.h"
>>>> +
>>>> +#include "arguments.h"
>>>> +
>>>> +#if HAVE_IFADDRS_H
>>>> +#include <ifaddrs.h>
>>>> +#else
>>>> +#include <../include/ifaddrs.h>
>>>> +#endif
>>>> +
>>>> +lxc_log_define(lxc_device, lxc);
>>>> +
>>>> +static const struct option my_longopts[] = {
>>>> +	LXC_COMMON_OPTIONS
>>>> +};
>>>> +
>>>> +static struct lxc_arguments my_args = {
>>>> +	.progname = "lxc-devicee",
>> Type above.
>>
>>>> +	.help     = "\
>>>> +--name=NAME -- COMMAND\n\
>>>> +\n\
>>>> +lxc-device attach or detach device to container.\n\
>>>> +lxc-device -n name add|del ifname.\n\
>>>> +\n\
>>>> +Options :\n\
>>>> +  -n, --name=NAME      NAME for name of the container",
>> Could be updated to ressemble the output from the other C programs a bit more.
>>
>>>> +	.options  = my_longopts,
>>>> +	.parser   = NULL,
>>>> +	.checker  = NULL,
>>>> +};
>>>> +
>>>> +static bool is_interface(const char* dev_name, pid_t pid)
>>>> +{
>>>> +	pid_t p = fork();
> Please do check for fork failure.
>
>>>> +	if (p == 0) {
>>>> +		struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
>>>> +
>>>> +		switch_to_newnet(pid);
> Check for failure.
>
>>>> +		/* Grab the list of interfaces */
>>>> +		if (getifaddrs(&interfaceArray)) {
>>>> +			ERROR("failed to get interfaces list");
>>>> +			exit(-1);
>>>> +		}
>>>> +
>>>> +		/* Iterate through the interfaces */
>>>> +		for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
>>>> +			if (strcmp(tempIfAddr->ifa_name, dev_name) == 0) {
>>>> +				exit(0);
>>>> +			}
>>>> +		}
>>>> +		exit(1);
>>>> +	}
>>>> +
>>>> +	if (wait_for_pid(p) == 0) {
>>>> +		return true;
>>>> +	}
>>>> +	return false;
>>>> +}
>>>> +
>>>> +int main(int argc, char *argv[])
>>>> +{
>>>> +	struct lxc_container *c;
>>>> +	char *cmd, *dev_name, *dst_name;
>>>> +	int ret = 1;
>>>> +
>>>> +	if (lxc_arguments_parse(&my_args, argc, argv))
>>>> +		goto err;
>>>> +
>>>> +	if (!my_args.log_file)
>>>> +		my_args.log_file = "none";
>>>> +
>>>> +	if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
>>>> +			 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
>>>> +		goto err;
>>>> +	lxc_log_options_no_override();
>>>> +
>>>> +	c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
>>>> +	if (!c) {
>>>> +		ERROR("No such container: %s:%s", my_args.lxcpath[0], my_args.name);
>> The standard error message for that is "%s doesn't exist", my_args.name
>>
>>>> +		goto err;
>>>> +	}
>>>> +
>>>> +	if (!c->is_running(c)) {
>>>> +		ERROR("Container %s is not running.", c->name);
>>>> +		goto err1;
>>>> +	}
>>>> +
>>>> +	if (my_args.argc < 2) {
>>>> +		ERROR(my_args.help);
>>>> +		goto err1;
>>>> +	}
>>>> +
>>>> +	cmd = my_args.argv[0];
>>>> +	dev_name = my_args.argv[1];
>>>> +	if (my_args.argc < 3)
>>>> +		dst_name = dev_name;
>>>> +	else
>>>> +		dst_name = my_args.argv[2];
>>>> +
>>>> +	if (strcmp(cmd, "add") == 0) {
>>>> +		if (is_interface(dev_name, 1)) {
>>>> +			ret = c->attach_interface(c, dev_name, dst_name);
>>>> +		} else {
>>>> +			ret = c->add_device_node(c, dev_name, dst_name);
>>>> +		}
>>>> +		if (ret != true) {
>>>> +			ERROR("Failed to add %s to %s.", dev_name, c->name);
>>>> +			ret = 1;
>>>> +			goto err1;
>>>> +		}
>>>> +		INFO("Added %s to %s.", dev_name, c->name);
>>>> +	} else if (strcmp(cmd, "del") == 0) {
>>>> +		if (is_interface(dev_name, c->init_pid(c))) {
>>>> +			ret = c->detach_interface(c, dev_name, dst_name);
>>>> +		} else {
>>>> +			ret = c->remove_device_node(c, dev_name, dst_name);
>>>> +		}
>>>> +		if (ret != true) {
>>>> +			ERROR("Failed to del %s from %s.", dev_name, c->name);
>>>> +			ret = 1;
>>>> +			goto err1;
>>>> +		}
>>>> +		INFO("Deled %s from %s.", dev_name, c->name);
>> Typo
>>
>>>> +	} else {
>>>> +		ERROR(my_args.help);
>>>> +		goto err1;
>>>> +	}
>>>> +	exit(0);
>>>> +err1:
>>>> +	lxc_container_put(c);
>>>> +err:
>>>> +	exit(ret);
>>>> +}
>>>> -- 
>>>> 1.8.4.2
>>>>
>> -- 
>> Stéphane Graber
>> Ubuntu developer
>> http://www.ubuntu.com
>
> .
>



More information about the lxc-devel mailing list