[lxc-devel] [PATCH 9/9] lxc-device: rewrite lxc-device.
Dongsheng Yang
yangds.fnst at cn.fujitsu.com
Fri Oct 10 03:17:00 UTC 2014
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>
---
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