]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce new domain create APIs to pass pre-opened FDs to LXC
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 9 Jul 2013 16:12:38 +0000 (17:12 +0100)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 18 Jul 2013 10:01:14 +0000 (11:01 +0100)
With container based virt, it is useful to be able to pass
pre-opened file descriptors to the container init process.
This allows for containers to be auto-activated from incoming
socket connections, passing the active socket into the container.

To do this, introduce a pair of new APIs, virDomainCreateXMLWithFiles
and virDomainCreateWithFiles, which accept an array of file
descriptors. For the LXC driver, UNIX file descriptor passing
will be used to send them to libvirtd, which will them pass
them down to libvirt_lxc, which will then pass them to the container
init process.

This will only be implemented for LXC right now, but the design
is generic enough it could work with other hypervisors, hence
I suggest adding this to libvirt.so, rather than libvirt-lxc.so

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
include/libvirt/libvirt.h.in
python/generator.py
python/libvirt-override-virConnect.py
python/libvirt-override-virDomain.py
python/libvirt-override.c
src/driver.h
src/libvirt.c
src/libvirt_public.syms

index 32c36f1b8d5d983b1b16f74b6e64fe12ef4361a1..01dc3a7302e66de44bfae9e4c087e6e5ff022189 100644 (file)
@@ -1575,6 +1575,11 @@ virConnectPtr           virDomainGetConnect     (virDomainPtr domain);
 virDomainPtr            virDomainCreateXML      (virConnectPtr conn,
                                                  const char *xmlDesc,
                                                  unsigned int flags);
+virDomainPtr            virDomainCreateXMLWithFiles(virConnectPtr conn,
+                                                    const char *xmlDesc,
+                                                    unsigned int nfiles,
+                                                    int *files,
+                                                    unsigned int flags);
 virDomainPtr            virDomainLookupByName   (virConnectPtr conn,
                                                  const char *name);
 virDomainPtr            virDomainLookupByID     (virConnectPtr conn,
@@ -2178,6 +2183,11 @@ int                     virDomainCreate         (virDomainPtr domain);
 int                     virDomainCreateWithFlags (virDomainPtr domain,
                                                   unsigned int flags);
 
+int                     virDomainCreateWithFiles (virDomainPtr domain,
+                                                  unsigned int nfiles,
+                                                  int *files,
+                                                  unsigned int flags);
+
 int                     virDomainGetAutostart   (virDomainPtr domain,
                                                  int *autostart);
 int                     virDomainSetAutostart   (virDomainPtr domain,
index da642eb677bb0d9b0acdf7b6357b18ee32860e56..427cebce3888d438d4ca9391141533d3f33c9eef 100755 (executable)
@@ -513,6 +513,9 @@ skip_function = (
     'virConnectUnregisterCloseCallback', # overriden in virConnect.py
     'virConnectRegisterCloseCallback', # overriden in virConnect.py
 
+    'virDomainCreateXMLWithFiles', # overriden in virConnect.py
+    'virDomainCreateWithFiles', # overriden in virDomain.py
+
     # 'Ref' functions have no use for bindings users.
     "virConnectRef",
     "virDomainRef",
index 5495b70f267f49fbe92ba162d5c12ca54e4dc435..a0f579d56e095b239fcb80f56bd1a5390b0481c6 100644 (file)
         if ret == -1:
             raise libvirtError ('virConnectRegisterCloseCallback() failed', conn=self)
         return ret
+
+    def createXMLWithFiles(self, xmlDesc, files, flags=0):
+        """Launch a new guest domain, based on an XML description similar
+        to the one returned by virDomainGetXMLDesc()
+        This function may require privileged access to the hypervisor.
+        The domain is not persistent, so its definition will disappear when it
+        is destroyed, or if the host is restarted (see virDomainDefineXML() to
+        define persistent domains).
+
+        @files provides an array of file descriptors which will be
+        made available to the 'init' process of the guest. The file
+        handles exposed to the guest will be renumbered to start
+        from 3 (ie immediately following stderr). This is only
+        supported for guests which use container based virtualization
+        technology.
+
+        If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+        will be started, but its CPUs will remain paused. The CPUs
+        can later be manually started using virDomainResume.
+
+        If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+        domain will be automatically destroyed when the virConnectPtr
+        object is finally released. This will also happen if the
+        client application crashes / loses its connection to the
+        libvirtd daemon. Any domains marked for auto destroy will
+        block attempts at migration, save-to-file, or snapshots. """
+        ret = libvirtmod.virDomainCreateXMLWithFiles(self._o, xmlDesc, files, flags)
+        if ret is None:raise libvirtError('virDomainCreateXMLWithFiles() failed', conn=self)
+        __tmp = virDomain(self,_obj=ret)
+        return __tmp
index 142b1d461783eefe7ba856c5659eb3a64a1fa3ef..c96cc5e0002c372f2d869369be5e6f62fb2b2635 100644 (file)
@@ -9,3 +9,41 @@
             retlist.append(virDomainSnapshot(self, _obj=snapptr))
 
         return retlist
+
+
+    def createWithFiles(self, files, flags=0):
+        """Launch a defined domain. If the call succeeds the domain moves from the
+        defined to the running domains pools.
+
+        @files provides an array of file descriptors which will be
+        made available to the 'init' process of the guest. The file
+        handles exposed to the guest will be renumbered to start
+        from 3 (ie immediately following stderr). This is only
+        supported for guests which use container based virtualization
+        technology.
+
+        If the VIR_DOMAIN_START_PAUSED flag is set, or if the guest domain
+        has a managed save image that requested paused state (see
+        virDomainManagedSave()) the guest domain will be started, but its
+        CPUs will remain paused. The CPUs can later be manually started
+        using virDomainResume().  In all other cases, the guest domain will
+        be running.
+
+        If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+        domain will be automatically destroyed when the virConnectPtr
+        object is finally released. This will also happen if the
+        client application crashes / loses its connection to the
+        libvirtd daemon. Any domains marked for auto destroy will
+        block attempts at migration, save-to-file, or snapshots.
+
+        If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a
+        managed save file for this domain (created by virDomainManagedSave()),
+        then libvirt will attempt to bypass the file system cache while restoring
+        the file, or fail if it cannot do so for the given system; this can allow
+        less pressure on file system cache, but also risks slowing loads from NFS.
+
+        If the VIR_DOMAIN_START_FORCE_BOOT flag is set, then any managed save
+        file for this domain is discarded, and the domain boots from scratch. """
+        ret = libvirtmod.virDomainCreateWithFiles(self._o, files, flags)
+        if ret == -1: raise libvirtError ('virDomainCreateWithFiles() failed', dom=self)
+        return ret
index 01c941e0b9a0217440f3bd153480b2577fc35246..0a108877fbc567322e703df7240b1ca95b2c0320 100644 (file)
@@ -7025,6 +7025,93 @@ error:
 }
 
 
+static PyObject *
+libvirt_virDomainCreateWithFiles(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+    PyObject *py_retval = NULL;
+    int c_retval;
+    virDomainPtr domain;
+    PyObject *pyobj_domain;
+    PyObject *pyobj_files;
+    unsigned int flags;
+    unsigned int nfiles;
+    int *files = NULL;
+    size_t i;
+
+    if (!PyArg_ParseTuple(args, (char *)"OOi:virDomainCreateWithFiles",
+                          &pyobj_domain, &pyobj_files, &flags))
+        return NULL;
+    domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain);
+
+    nfiles = PyList_Size(pyobj_files);
+
+    if (VIR_ALLOC_N_QUIET(files, nfiles) < 0)
+        return PyErr_NoMemory();
+
+    for (i = 0; i < nfiles; i++) {
+        PyObject *pyfd;
+        int fd;
+
+        pyfd = PyList_GetItem(pyobj_files, i);
+
+        if (libvirt_intUnwrap(pyfd, &fd) < 0)
+            goto cleanup;
+    }
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    c_retval = virDomainCreateWithFiles(domain, nfiles, files, flags);
+    LIBVIRT_END_ALLOW_THREADS;
+    py_retval = libvirt_intWrap((int) c_retval);
+
+cleanup:
+    VIR_FREE(files);
+    return py_retval;
+}
+
+
+static PyObject *
+libvirt_virDomainCreateXMLWithFiles(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
+    PyObject *py_retval = NULL;
+    virDomainPtr c_retval;
+    virConnectPtr conn;
+    PyObject *pyobj_conn;
+    char * xmlDesc;
+    PyObject *pyobj_files;
+    unsigned int flags;
+    unsigned int nfiles;
+    int *files = NULL;
+    size_t i;
+
+    if (!PyArg_ParseTuple(args, (char *)"OzOi:virDomainCreateXMLWithFiles",
+                          &pyobj_conn, &xmlDesc, &pyobj_files, &flags))
+        return NULL;
+    conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn);
+
+    nfiles = PyList_Size(pyobj_files);
+
+    if (VIR_ALLOC_N_QUIET(files, nfiles) < 0)
+        return PyErr_NoMemory();
+
+    for (i = 0; i < nfiles; i++) {
+        PyObject *pyfd;
+        int fd;
+
+        pyfd = PyList_GetItem(pyobj_files, i);
+
+        if (libvirt_intUnwrap(pyfd, &fd) < 0)
+            goto cleanup;
+    }
+
+    LIBVIRT_BEGIN_ALLOW_THREADS;
+    c_retval = virDomainCreateXMLWithFiles(conn, xmlDesc, nfiles, files, flags);
+    LIBVIRT_END_ALLOW_THREADS;
+    py_retval = libvirt_virDomainPtrWrap((virDomainPtr) c_retval);
+
+cleanup:
+    VIR_FREE(files);
+    return py_retval;
+}
+
+
 /************************************************************************
  *                                                                     *
  *                     The registration stuff                          *
@@ -7150,6 +7237,8 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virNodeGetMemoryParameters", libvirt_virNodeGetMemoryParameters, METH_VARARGS, NULL},
     {(char *) "virNodeSetMemoryParameters", libvirt_virNodeSetMemoryParameters, METH_VARARGS, NULL},
     {(char *) "virNodeGetCPUMap", libvirt_virNodeGetCPUMap, METH_VARARGS, NULL},
+    {(char *) "virDomainCreateXMLWithFiles", libvirt_virDomainCreateXMLWithFiles, METH_VARARGS, NULL},
+    {(char *) "virDomainCreateWithFiles", libvirt_virDomainCreateWithFiles, METH_VARARGS, NULL},
     {NULL, NULL, 0, NULL}
 };
 
index da030215c573670320fafe0951f3b5d5b4195b57..cc03e9f768208484a076fdef71599e35c9f38404 100644 (file)
@@ -136,6 +136,12 @@ typedef virDomainPtr
 (*virDrvDomainCreateXML)(virConnectPtr conn,
                          const char *xmlDesc,
                          unsigned int flags);
+typedef virDomainPtr
+(*virDrvDomainCreateXMLWithFiles)(virConnectPtr conn,
+                                  const char *xmlDesc,
+                                  unsigned int nfiles,
+                                  int *files,
+                                  unsigned int flags);
 
 typedef virDomainPtr
 (*virDrvDomainLookupByID)(virConnectPtr conn,
@@ -339,6 +345,11 @@ typedef int
 typedef int
 (*virDrvDomainCreateWithFlags)(virDomainPtr dom,
                                unsigned int flags);
+typedef int
+(*virDrvDomainCreateWithFiles)(virDomainPtr dom,
+                               unsigned int nfiles,
+                               int *files,
+                               unsigned int flags);
 
 typedef virDomainPtr
 (*virDrvDomainDefineXML)(virConnectPtr conn,
@@ -1144,6 +1155,7 @@ struct _virDriver {
     virDrvConnectNumOfDomains connectNumOfDomains;
     virDrvConnectListAllDomains connectListAllDomains;
     virDrvDomainCreateXML domainCreateXML;
+    virDrvDomainCreateXMLWithFiles domainCreateXMLWithFiles;
     virDrvDomainLookupByID domainLookupByID;
     virDrvDomainLookupByUUID domainLookupByUUID;
     virDrvDomainLookupByName domainLookupByName;
@@ -1201,6 +1213,7 @@ struct _virDriver {
     virDrvConnectNumOfDefinedDomains connectNumOfDefinedDomains;
     virDrvDomainCreate domainCreate;
     virDrvDomainCreateWithFlags domainCreateWithFlags;
+    virDrvDomainCreateWithFiles domainCreateWithFiles;
     virDrvDomainDefineXML domainDefineXML;
     virDrvDomainUndefine domainUndefine;
     virDrvDomainUndefineFlags domainUndefineFlags;
index 0cdac0d2afe50c338d90d6a35695e10dc0e75609..873b4e17caffa03bb06325f3879ee494cb6b50d8 100644 (file)
@@ -2003,6 +2003,79 @@ error:
     return NULL;
 }
 
+/**
+ * virDomainCreateXMLWithFiles:
+ * @conn: pointer to the hypervisor connection
+ * @xmlDesc: string containing an XML description of the domain
+ * @nfiles: number of file descriptors passed
+ * @files: list of file descriptors passed
+ * @flags: bitwise-OR of supported virDomainCreateFlags
+ *
+ * Launch a new guest domain, based on an XML description similar
+ * to the one returned by virDomainGetXMLDesc()
+ * This function may require privileged access to the hypervisor.
+ * The domain is not persistent, so its definition will disappear when it
+ * is destroyed, or if the host is restarted (see virDomainDefineXML() to
+ * define persistent domains).
+ *
+ * @files provides an array of file descriptors which will be
+ * made available to the 'init' process of the guest. The file
+ * handles exposed to the guest will be renumbered to start
+ * from 3 (ie immediately following stderr). This is only
+ * supported for guests which use container based virtualization
+ * technology.
+ *
+ * If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain
+ * will be started, but its CPUs will remain paused. The CPUs
+ * can later be manually started using virDomainResume.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / loses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration, save-to-file, or snapshots.
+ *
+ * Returns a new domain object or NULL in case of failure
+ */
+virDomainPtr
+virDomainCreateXMLWithFiles(virConnectPtr conn, const char *xmlDesc,
+                            unsigned int nfiles,
+                            int *files,
+                            unsigned int flags)
+{
+    VIR_DEBUG("conn=%p, xmlDesc=%s, nfiles=%u, files=%p, flags=%x",
+              conn, xmlDesc, nfiles, files, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECT(conn)) {
+        virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+        virDispatchError(NULL);
+        return NULL;
+    }
+    virCheckNonNullArgGoto(xmlDesc, error);
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibConnError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainCreateXMLWithFiles) {
+        virDomainPtr ret;
+        ret = conn->driver->domainCreateXMLWithFiles(conn, xmlDesc,
+                                                     nfiles, files,
+                                                     flags);
+        if (!ret)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+error:
+    virDispatchError(conn);
+    return NULL;
+}
+
 /**
  * virDomainCreateLinux:
  * @conn: pointer to the hypervisor connection
@@ -9424,6 +9497,87 @@ error:
     return -1;
 }
 
+/**
+ * virDomainCreateWithFiles:
+ * @domain: pointer to a defined domain
+ * @nfiles: number of file descriptors passed
+ * @files: list of file descriptors passed
+ * @flags: bitwise-OR of supported virDomainCreateFlags
+ *
+ * Launch a defined domain. If the call succeeds the domain moves from the
+ * defined to the running domains pools.
+ *
+ * @files provides an array of file descriptors which will be
+ * made available to the 'init' process of the guest. The file
+ * handles exposed to the guest will be renumbered to start
+ * from 3 (ie immediately following stderr). This is only
+ * supported for guests which use container based virtualization
+ * technology.
+ *
+ * If the VIR_DOMAIN_START_PAUSED flag is set, or if the guest domain
+ * has a managed save image that requested paused state (see
+ * virDomainManagedSave()) the guest domain will be started, but its
+ * CPUs will remain paused. The CPUs can later be manually started
+ * using virDomainResume().  In all other cases, the guest domain will
+ * be running.
+ *
+ * If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest
+ * domain will be automatically destroyed when the virConnectPtr
+ * object is finally released. This will also happen if the
+ * client application crashes / loses its connection to the
+ * libvirtd daemon. Any domains marked for auto destroy will
+ * block attempts at migration, save-to-file, or snapshots.
+ *
+ * If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a
+ * managed save file for this domain (created by virDomainManagedSave()),
+ * then libvirt will attempt to bypass the file system cache while restoring
+ * the file, or fail if it cannot do so for the given system; this can allow
+ * less pressure on file system cache, but also risks slowing loads from NFS.
+ *
+ * If the VIR_DOMAIN_START_FORCE_BOOT flag is set, then any managed save
+ * file for this domain is discarded, and the domain boots from scratch.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+virDomainCreateWithFiles(virDomainPtr domain, unsigned int nfiles,
+                         int *files, unsigned int flags)
+{
+    virConnectPtr conn;
+
+    VIR_DOMAIN_DEBUG(domain, "nfiles=%u, files=%p, flags=%x",
+                     nfiles, files, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+    conn = domain->conn;
+    if (conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (conn->driver->domainCreateWithFiles) {
+        int ret;
+        ret = conn->driver->domainCreateWithFiles(domain,
+                                                  nfiles, files,
+                                                  flags);
+        if (ret < 0)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(domain->conn);
+    return -1;
+}
+
 /**
  * virDomainGetAutostart:
  * @domain: a domain object
index 4be5104db19fd40c6ec69741e01c2c0eed7bda42..bbdf78ac222f14c39a5bd3cc264dc9aa7f54a70b 100644 (file)
@@ -629,6 +629,8 @@ LIBVIRT_1.1.0 {
 
 LIBVIRT_1.1.1 {
     global:
+        virDomainCreateWithFiles;
+        virDomainCreateXMLWithFiles;
         virDomainSetMemoryStatsPeriod;
 } LIBVIRT_1.1.0;