[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