[lxc-devel] [PATCH 9/9] lxc-device: rewrite lxc-device.
Serge Hallyn
serge.hallyn at ubuntu.com
Tue Oct 14 12:36:53 UTC 2014
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.
>
> Signed-off-by: Dongsheng Yang <yangds.fnst at cn.fujitsu.com>
> Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
Yes, but how about we add a check for !geteuid() at the
top of main() ?
> ---
> src/lxc/Makefile.am | 4 +-
> src/lxc/lxc-device | 97 -----------------------------
> src/lxc/lxc_device.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 175 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 da3f78e..840e1c7 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -163,13 +163,11 @@ endif
> bin_SCRIPTS = lxc-checkconfig
>
> EXTRA_DIST = \
> - lxc-device \
> lxc-ls \
> lxc-restore-net \
> lxc-top.lua
>
> if ENABLE_PYTHON
> -bin_SCRIPTS += lxc-device
> bin_SCRIPTS += lxc-ls
> bin_SCRIPTS += lxc-start-ephemeral
> else
> @@ -186,6 +184,7 @@ bin_PROGRAMS = \
> lxc-console \
> lxc-create \
> lxc-destroy \
> + lxc-device \
> lxc-execute \
> lxc-freeze \
> lxc-info \
> @@ -218,6 +217,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..68c4802
> --- /dev/null
> +++ b/src/lxc/lxc_device.c
> @@ -0,0 +1,173 @@
> +/*
> + * 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-device",
> + .help = "\
> +--name=NAME -- add|del DEV\n\
> +\n\
> +lxc-device attach or detach DEV to or from container.\n\
> +\n\
> +Options :\n\
> + -n, --name=NAME NAME for name of the container",
> + .options = my_longopts,
> + .parser = NULL,
> + .checker = NULL,
> +};
> +
> +static bool is_interface(const char* dev_name, pid_t pid)
> +{
> + pid_t p = fork();
> +
> + if (p < 0) {
> + SYSERROR("failed to fork task.");
> + exit(1);
> + }
> +
> + if (p == 0) {
> + struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
> +
> + if (!switch_to_ns(pid, "net")) {
> + ERROR("failed to enter netns of container.");
> + exit(-1);
> + }
> +
> + /* 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("%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("Add %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("Delete %s from %s.", dev_name, c->name);
> + } else {
> + ERROR(my_args.help);
> + goto err1;
> + }
> + exit(0);
> +err1:
> + lxc_container_put(c);
> +err:
> + exit(ret);
> +}
> --
> 1.8.4.2
>
More information about the lxc-devel
mailing list