]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add 'lxc-enter-namespace' command to virsh
authorDaniel P. Berrange <berrange@redhat.com>
Fri, 21 Dec 2012 16:51:33 +0000 (16:51 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 15 Jan 2013 19:09:47 +0000 (19:09 +0000)
Add a 'lxc-enter-namespace' command which accepts a domain name
and then a command + args to run, attached to the container

eg

  virsh -c lxc:/// lxc-enter-namespace demo -- /bin/ps -auxf

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
tools/Makefile.am
tools/virsh-domain.c
tools/virsh.pod

index 878a1140bf5bc3aa3f7124932930d05cf1c3bdd5..8a0429caedb51585945b4af1a7ee83eeb3cec04d 100644 (file)
@@ -133,6 +133,7 @@ virsh_LDADD =                                                       \
                $(STATIC_BINARIES)                              \
                $(WARN_CFLAGS)                                  \
                ../src/libvirt.la                               \
+               ../src/libvirt-lxc.la                           \
                ../src/libvirt-qemu.la                          \
                ../gnulib/lib/libgnu.la                         \
                $(LIBXML_LIBS)                                  \
index e91939c6b1caf3260c72ad7eab384bf2ec3be2f1..e3ff5d3a1a498bdd3469399d1ad6d826b9dc375d 100644 (file)
 #include "conf/domain_conf.h"
 #include "console.h"
 #include "viralloc.h"
+#include "vircommand.h"
 #include "virutil.h"
 #include "virfile.h"
 #include "virjson.h"
 #include "virkeycode.h"
 #include "virmacaddr.h"
+#include "virprocess.h"
 #include "virstring.h"
 #include "virsh-domain-monitor.h"
 #include "virerror.h"
@@ -6770,6 +6772,98 @@ cleanup:
     return ret;
 }
 
+/*
+ * "lxc-enter-namespace" namespace
+ */
+static const vshCmdInfo info_lxc_enter_namespace[] = {
+    {"help", N_("LXC Guest Enter Namespace")},
+    {"desc", N_("Run an arbitrary lxc guest enter namespace; use at your own risk")},
+    {NULL, NULL}
+};
+
+static const vshCmdOptDef opts_lxc_enter_namespace[] = {
+    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"cmd", VSH_OT_ARGV, VSH_OFLAG_REQ, N_("namespace")},
+    {NULL, 0, 0, NULL}
+};
+
+static bool
+cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
+{
+    virDomainPtr dom = NULL;
+    bool ret = false;
+    const vshCmdOpt *opt = NULL;
+    char **cmdargv = NULL;
+    size_t ncmdargv = 0;
+    pid_t pid;
+    int nfdlist;
+    int *fdlist;
+    size_t i;
+
+    dom = vshCommandOptDomain(ctl, cmd, NULL);
+    if (dom == NULL)
+        goto cleanup;
+
+    while ((opt = vshCommandOptArgv(cmd, opt))) {
+        if (VIR_EXPAND_N(cmdargv, ncmdargv, 1) < 0) {
+            vshError(ctl, _("%s: %d: failed to allocate argv"),
+                     __FILE__, __LINE__);
+        }
+        cmdargv[ncmdargv-1] = opt->data;
+    }
+    if (VIR_EXPAND_N(cmdargv, ncmdargv, 1) < 0) {
+        vshError(ctl, _("%s: %d: failed to allocate argv"),
+                 __FILE__, __LINE__);
+    }
+    cmdargv[ncmdargv - 1] = NULL;
+
+    if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0)
+        goto cleanup;
+
+    /* Fork once because we don't want to affect
+     * virsh's namespace itself
+     */
+    if (virFork(&pid) < 0)
+        goto cleanup;
+    if (pid == 0) {
+        if (virDomainLxcEnterNamespace(dom,
+                                       nfdlist,
+                                       fdlist,
+                                       NULL,
+                                       NULL,
+                                       0) < 0)
+            _exit(255);
+
+        /* Fork a second time because entering the
+         * pid namespace only takes effect after fork
+         */
+        if (virFork(&pid) < 0)
+            _exit(255);
+        if (pid == 0) {
+            execv(cmdargv[0], cmdargv);
+            _exit(255);
+        } else {
+            if (virProcessWait(pid, NULL) < 0)
+                _exit(255);
+        }
+        _exit(0);
+    } else {
+        for (i = 0 ; i < nfdlist ; i++)
+            VIR_FORCE_CLOSE(fdlist[i]);
+        VIR_FREE(fdlist);
+        if (virProcessWait(pid, NULL) < 0)
+            goto cleanup;
+    }
+
+    ret = true;
+
+cleanup:
+    if (dom)
+        virDomainFree(dom);
+    VIR_FREE(cmdargv);
+    return ret;
+}
+
 /*
  * "dumpxml" command
  */
@@ -8760,6 +8854,7 @@ const vshCmdDef domManagementCmds[] = {
     {"inject-nmi", cmdInjectNMI, opts_inject_nmi, info_inject_nmi, 0},
     {"send-key", cmdSendKey, opts_send_key, info_send_key, 0},
     {"send-process-signal", cmdSendProcessSignal, opts_send_process_signal, info_send_process_signal, 0},
+    {"lxc-enter-namespace", cmdLxcEnterNamespace, opts_lxc_enter_namespace, info_lxc_enter_namespace, 0},
     {"managedsave", cmdManagedSave, opts_managedsave, info_managedsave, 0},
     {"managedsave-remove", cmdManagedSaveRemove, opts_managedsaveremove,
      info_managedsaveremove, 0},
index c9ebc8f09bfd51f7acd498a343174eb18376917e..e2a2aeca9518480e518fdc73517c61a70ceaef7f 100644 (file)
@@ -3056,6 +3056,14 @@ When I<--aysnc> is given, the command waits for timeout whether success or
 failed. And when I<--block> is given, the command waits forever with blocking
 timeout.
 
+=item B<lxc-enter-namespace> I<domain> -- /path/to/binary [arg1, [arg2, ...]]
+
+Enter the namespace of I<domain> and execute the command C</path/to/binary>
+passing the requested args. The binary path is relative to the container
+root filesystem, not the host root filesystem. The binary will inherit the
+environment variables / console visible to virsh. This command only works
+when connected to the LXC hypervisor driver.
+
 =back
 
 =head1 ENVIRONMENT