From: "Daniel P. Berrange" <berrange(a)redhat.com>
Add a "--pass-fds N,M,..." arg to the virsh start/create
methods. This allows pre-opened file descriptors from the
shell to be passed on into the guest
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
tools/virsh-domain.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++---
tools/virsh.pod | 13 ++++++++-
2 files changed, 90 insertions(+), 5 deletions(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c08b0e9..606bcdf 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -3256,9 +3256,61 @@ static const vshCmdOptDef opts_start[] = {
.type = VSH_OT_BOOL,
.help = N_("force fresh boot by discarding any managed save")
},
+ {.name = "pass-fds",
+ .type = VSH_OT_STRING,
+ .help = N_("pass file descriptors N,M,... to the guest")
+ },
{.name = NULL}
};
+static int
+cmdStartGetFDs(vshControl *ctl,
+ const vshCmd *cmd,
+ size_t *nfdsret,
+ int **fdsret)
+{
+ const char *fdopt;
+ char **fdlist = NULL;
+ int *fds = NULL;
+ size_t nfds = 0;
+ size_t i;
+
+ *nfdsret = 0;
+ *fdsret = NULL;
+
+ if (vshCommandOptString(cmd, "pass-fds", &fdopt) <= 0)
+ return 0;
+
+ if (!(fdlist = virStringSplit(fdopt, ",", -1))) {
+ vshError(ctl, _("Unable to split FD list '%s'"), fdopt);
+ return -1;
+ }
+
+ for (i = 0; fdlist[i] != NULL; i++) {
+ int fd;
+ if (virStrToLong_i(fdlist[i], NULL, 10, &fd) < 0) {
+ vshError(ctl, _("Unable to parse FD number '%s'"),
fdlist[i]);
+ goto error;
+ }
+ if (VIR_EXPAND_N(fds, nfds, 1) < 0) {
+ vshError(ctl, "%s", _("Unable to allocate FD list"));
+ goto error;
+ }
+ fds[nfds - 1] = fd;
+ }
+
+ virStringFreeList(fdlist);
+
+ *fdsret = fds;
+ *nfdsret = nfds;
+ return 0;
+
+error:
+ virStringFreeList(fdlist);
+ VIR_FREE(fds);
+ return -1;
+}
+
static bool
cmdStart(vshControl *ctl, const vshCmd *cmd)
{
@@ -3269,6 +3321,8 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
#endif
unsigned int flags = VIR_DOMAIN_NONE;
int rc;
+ size_t nfds = 0;
+ int *fds = NULL;
if (!(dom = vshCommandOptDomainBy(ctl, cmd, NULL,
VSH_BYNAME | VSH_BYUUID)))
@@ -3280,6 +3334,9 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
return false;
}
+ if (cmdStartGetFDs(ctl, cmd, &nfds, &fds) < 0)
+ return false;
+
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
if (vshCommandOptBool(cmd, "autodestroy"))
@@ -3291,7 +3348,9 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
/* We can emulate force boot, even for older servers that reject it. */
if (flags & VIR_DOMAIN_START_FORCE_BOOT) {
- if (virDomainCreateWithFlags(dom, flags) == 0)
+ if ((nfds ?
+ virDomainCreateWithFiles(dom, nfds, fds, flags) :
+ virDomainCreateWithFlags(dom, flags)) == 0)
goto started;
if (last_error->code != VIR_ERR_NO_SUPPORT &&
last_error->code != VIR_ERR_INVALID_ARG) {
@@ -3313,8 +3372,9 @@ cmdStart(vshControl *ctl, const vshCmd *cmd)
}
/* Prefer older API unless we have to pass a flag. */
- if ((flags ? virDomainCreateWithFlags(dom, flags)
- : virDomainCreate(dom)) < 0) {
+ if ((nfds ? virDomainCreateWithFiles(dom, nfds, fds, flags) :
+ (flags ? virDomainCreateWithFlags(dom, flags)
+ : virDomainCreate(dom))) < 0) {
vshError(ctl, _("Failed to start domain %s"), virDomainGetName(dom));
goto cleanup;
}
@@ -3331,6 +3391,7 @@ started:
cleanup:
virDomainFree(dom);
+ VIR_FREE(fds);
return ret;
}
@@ -6397,6 +6458,10 @@ static const vshCmdOptDef opts_create[] = {
.type = VSH_OT_BOOL,
.help = N_("automatically destroy the guest when virsh disconnects")
},
+ {.name = "pass-fds",
+ .type = VSH_OT_STRING,
+ .help = N_("pass file descriptors N,M,... to the guest")
+ },
{.name = NULL}
};
@@ -6411,6 +6476,8 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd)
bool console = vshCommandOptBool(cmd, "console");
#endif
unsigned int flags = VIR_DOMAIN_NONE;
+ size_t nfds = 0;
+ int *fds = NULL;
if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
return false;
@@ -6418,12 +6485,18 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd)
if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
return false;
+ if (cmdStartGetFDs(ctl, cmd, &nfds, &fds) < 0)
+ return false;
+
if (vshCommandOptBool(cmd, "paused"))
flags |= VIR_DOMAIN_START_PAUSED;
if (vshCommandOptBool(cmd, "autodestroy"))
flags |= VIR_DOMAIN_START_AUTODESTROY;
- dom = virDomainCreateXML(ctl->conn, buffer, flags);
+ if (nfds)
+ dom = virDomainCreateXMLWithFiles(ctl->conn, buffer, nfds, fds, flags);
+ else
+ dom = virDomainCreateXML(ctl->conn, buffer, flags);
VIR_FREE(buffer);
if (dom != NULL) {
@@ -6438,6 +6511,7 @@ cmdCreate(vshControl *ctl, const vshCmd *cmd)
vshError(ctl, _("Failed to create domain from %s"), from);
ret = false;
}
+ VIR_FREE(fds);
return ret;
}
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 94fe897..8a9d2d0 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -539,6 +539,7 @@ the I<--force> flag may be specified, requesting to disconnect
any existing
sessions, such as in a case of a broken connection.
=item B<create> I<FILE> [I<--console>] [I<--paused>]
[I<--autodestroy>]
+[I<--pass-fds N,M,...>]
Create a domain from an XML <file>. An easy way to create the XML
<file> is to use the B<dumpxml> command to obtain the definition of a
@@ -549,6 +550,11 @@ If I<--autodestroy> is requested, then the guest will be
automatically
destroyed when virsh closes its connection to libvirt, or otherwise
exits.
+If I<--pass-fds> is specified, the argument is a comma separated list
+of open file descriptors which should be pass on into the guest. The
+file descriptors will be re-numered in the guest, starting from 3. This
+is only supported with container based virtualization.
+
B<Example>
virsh dumpxml <domain> > domain.xml
@@ -1661,7 +1667,7 @@ For strict control over ordering, use a single mode at a time and
repeat the command.
=item B<start> I<domain-name-or-uuid> [I<--console>]
[I<--paused>]
-[I<--autodestroy>] [I<--bypass-cache>] [I<--force-boot>]
+[I<--autodestroy>] [I<--bypass-cache>] [I<--force-boot>]
[I<--pass-fds N,M,...>]
Start a (previously defined) inactive domain, either from the last
B<managedsave> state, or via a fresh boot if no managedsave state is
@@ -1675,6 +1681,11 @@ the restore will avoid the file system cache, although this may
slow
down the operation. If I<--force-boot> is specified, then any
managedsave state is discarded and a fresh boot occurs.
+If I<--pass-fds> is specified, the argument is a comma separated list
+of open file descriptors which should be pass on into the guest. The
+file descriptors will be re-numered in the guest, starting from 3. This
+is only supported with container based virtualization.
+
=item B<suspend> I<domain>
Suspend a running domain. It is kept in memory but won't be scheduled
--
1.8.1.4