[Libvir] Unified Xen patch (second version)

Daniel P. Berrange berrange at redhat.com
Mon Apr 2 16:16:22 UTC 2007


On Mon, Apr 02, 2007 at 03:15:37PM +0100, Richard W.M. Jones wrote:
> >>+static int
> >>+qemuNetworkClose (virConnectPtr conn ATTRIBUTE_UNUSED)
> >>+{
> >>+    /* NB: This will fail to close the connection properly
> >>+     * qemuRegister is changed so that it only registers the
> >>+     * network (not the connection driver).
> >>+     */
> >>+    return 0;
> >>+}
> >
> >I'm not sure what you mean by this comment ? I'm fairly sure we need to 
> >have
> >code in qemuNetworkClose() though to close the QEMU socket when the XenD
> >driver is used QEMU driver for the networking APIs.
> 
> So the current code is complicated and somewhat devious.  In the current 
> code, the qemu network close just reuses qemuClose.  In the unified case 
> this fails because it tries to double-free a structure.
> 
> My first time around this I got around the double-free by keeping track 
> with a usage counter.  However that had its own problems, so seeing that 
> currently we always register the qemu connection and qemu network 
> drivers together, I just created a separate qemuNetworkClose function 
> which does nothing.  If on the other hand in future we will use qemu 
> network without qemu connections, then we'll need to change this (hence 
> added comments).  Note that this applies to registration (ie. 
> vir*Register), not whether or not we manage to connect to libvirtd.

The Xen driver *already* activates the QEMU networking driver so we
have to deal with that situation now. virsh net-list for example fails
with this patch applied now.

The problem is that QEMU network driver impl with this patch is just casting
the privateData straight to qemudPrivatePtr regardless of whether the QEMU
driver is actually active.

I'm attaching a patch which applies on-top of yours to change the qemudNetworkOpen
method to allocate a block of private data specific for the neworking functions.
If the conn->driver->name == QEMU, then we re-use the existing QEMUD socket,
otherwise we open a new one.

> 
> >Apart from the 2 questions about  suspend/resume/destroy APIs  and the QEMU
> >networking code, this patch looks fine for inclusion to me. Although it is
> >a big patch, it is basically a straight forward re-factoring with no major
> >operational changes aside from in the open/close routines.
> >
> >I'm going to  actually try it out for real shortly....
> 
> Yeah, I'm also testing it now.

I discovered the aforemetioned issue with Xen driver not being able to use
any of the network driver methods.

There was another interaction with the proxy code - the proxy driver should
not be activated if running as root. In addition if running as non-root,
any Xen driver is allowed to fail, except for the proxy driver. The attached
patch tries to alter the xen_unified.c do_open logic to deal with that.

The proxy itself was SEGV'ing because it didn't allocate the private data
blob, so the patch fixes that too.

I can now open  QEMU & XEn as root, and use networking functions, as well
as opening both as non-root.

Finally, the libvirt.c was not checking if conn->networkDriver was NULL,
so if no network driver was activated, the code would SEGV on any network
functions instead of returning operation not supported error.

Regards,
Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
diff -rup libvirt-pristine/src/libvirt.c libvirt/src/libvirt.c
--- libvirt-pristine/src/libvirt.c	2007-04-02 11:42:00.000000000 -0400
+++ libvirt/src/libvirt.c	2007-04-02 12:03:09.000000000 -0400
@@ -360,7 +360,8 @@ virConnectClose(virConnectPtr conn)
         return (-1);
 
     conn->driver->close (conn);
-    conn->networkDriver->close (conn);
+    if (conn->networkDriver)
+        conn->networkDriver->close (conn);
 
     if (virFreeConnect(conn) < 0)
         return (-1);
@@ -1900,7 +1901,7 @@ virConnectNumOfNetworks(virConnectPtr co
         return (-1);
     }
 
-    if (conn->networkDriver->numOfNetworks)
+    if (conn->networkDriver && conn->networkDriver->numOfNetworks)
         return conn->networkDriver->numOfNetworks (conn);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -1930,7 +1931,7 @@ virConnectListNetworks(virConnectPtr con
         return (-1);
     }
 
-    if (conn->networkDriver->listNetworks)
+    if (conn->networkDriver && conn->networkDriver->listNetworks)
         return conn->networkDriver->listNetworks (conn, names, maxnames);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -1953,7 +1954,7 @@ virConnectNumOfDefinedNetworks(virConnec
         return (-1);
     }
 
-    if (conn->networkDriver->numOfDefinedNetworks)
+    if (conn->networkDriver && conn->networkDriver->numOfDefinedNetworks)
         return conn->networkDriver->numOfDefinedNetworks (conn);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -1984,7 +1985,7 @@ virConnectListDefinedNetworks(virConnect
         return (-1);
     }
 
-    if (conn->networkDriver->listDefinedNetworks)
+    if (conn->networkDriver && conn->networkDriver->listDefinedNetworks)
         return conn->networkDriver->listDefinedNetworks (conn,
                                                          names, maxnames);
 
@@ -2013,7 +2014,7 @@ virNetworkLookupByName(virConnectPtr con
         return (NULL);
     }
 
-    if (conn->networkDriver->networkLookupByName)
+    if (conn->networkDriver && conn->networkDriver->networkLookupByName)
         return conn->networkDriver->networkLookupByName (conn, name);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2041,7 +2042,7 @@ virNetworkLookupByUUID(virConnectPtr con
         return (NULL);
     }
 
-    if (conn->networkDriver->networkLookupByUUID)
+    if (conn->networkDriver && conn->networkDriver->networkLookupByUUID)
         return conn->networkDriver->networkLookupByUUID (conn, uuid);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2123,7 +2124,7 @@ virNetworkCreateXML(virConnectPtr conn, 
 	return (NULL);
     }
 
-    if (conn->networkDriver->networkCreateXML)
+    if (conn->networkDriver && conn->networkDriver->networkCreateXML)
         return conn->networkDriver->networkCreateXML (conn, xmlDesc);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2155,7 +2156,7 @@ virNetworkDefineXML(virConnectPtr conn, 
         return (NULL);
     }
 
-    if (conn->networkDriver->networkDefineXML)
+    if (conn->networkDriver && conn->networkDriver->networkDefineXML)
         return conn->networkDriver->networkDefineXML (conn, xml);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2184,7 +2185,7 @@ virNetworkUndefine(virNetworkPtr network
 	return (-1);
     }
 
-    if (conn->networkDriver->networkUndefine)
+    if (conn->networkDriver && conn->networkDriver->networkUndefine)
         return conn->networkDriver->networkUndefine (network);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2218,7 +2219,7 @@ virNetworkCreate(virNetworkPtr network)
 	return (-1);
     }
 
-    if (conn->networkDriver->networkCreate)
+    if (conn->networkDriver && conn->networkDriver->networkCreate)
         return conn->networkDriver->networkCreate (network);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2253,7 +2254,7 @@ virNetworkDestroy(virNetworkPtr network)
 	return (-1);
     }
 
-    if (conn->networkDriver->networkDestroy)
+    if (conn->networkDriver && conn->networkDriver->networkDestroy)
         return conn->networkDriver->networkDestroy (network);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2389,7 +2390,7 @@ virNetworkGetXMLDesc(virNetworkPtr netwo
 
     conn = network->conn;
 
-    if (conn->networkDriver->networkDumpXML)
+    if (conn->networkDriver && conn->networkDriver->networkDumpXML)
         return conn->networkDriver->networkDumpXML (network, flags);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2418,7 +2419,7 @@ virNetworkGetBridgeName(virNetworkPtr ne
 
     conn = network->conn;
 
-    if (conn->networkDriver->networkGetBridgeName)
+    if (conn->networkDriver && conn->networkDriver->networkGetBridgeName)
         return conn->networkDriver->networkGetBridgeName (network);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2453,7 +2454,7 @@ virNetworkGetAutostart(virNetworkPtr net
 
     conn = network->conn;
 
-    if (conn->networkDriver->networkGetAutostart)
+    if (conn->networkDriver && conn->networkDriver->networkGetAutostart)
         return conn->networkDriver->networkGetAutostart (network, autostart);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
@@ -2483,7 +2484,7 @@ virNetworkSetAutostart(virNetworkPtr net
 
     conn = network->conn;
 
-    if (conn->networkDriver->networkSetAutostart)
+    if (conn->networkDriver && conn->networkDriver->networkSetAutostart)
         return conn->networkDriver->networkSetAutostart (network, autostart);
 
     virLibConnError (conn, VIR_ERR_CALL_FAILED, __FUNCTION__);
diff -rup libvirt-pristine/src/qemu_internal.c libvirt/src/qemu_internal.c
--- libvirt-pristine/src/qemu_internal.c	2007-04-02 11:42:00.000000000 -0400
+++ libvirt/src/qemu_internal.c	2007-04-02 11:40:31.000000000 -0400
@@ -56,7 +56,12 @@
 struct _qemuPrivate {
     int qemud_fd;               /* Connection to libvirt qemu daemon. */
 };
+struct _qemuNetworkPrivate {
+    int qemud_fd;
+    int shared;
+};
 typedef struct _qemuPrivate *qemuPrivatePtr;
+typedef struct _qemuNetworkPrivate *qemuNetworkPrivatePtr;
 
 static void
 qemuError(virConnectPtr con,
@@ -217,11 +222,11 @@ qemuForkServer(void)
  * Returns the associated file descriptor or -1 in case of failure
  */
 static int
-qemuOpenClientUNIX(virConnectPtr conn, const char *path, int autostart) {
+qemuOpenClientUNIX(virConnectPtr conn ATTRIBUTE_UNUSED,
+                   const char *path, int autostart) {
     int fd;
     struct sockaddr_un addr;
     int trials = 0;
-    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
  retry:
     fd = socket(PF_UNIX, SOCK_STREAM, 0);
@@ -254,9 +259,7 @@ qemuOpenClientUNIX(virConnectPtr conn, c
         return VIR_DRV_OPEN_ERROR;
     }
 
-    priv->qemud_fd = fd;
-
-    return VIR_DRV_OPEN_SUCCESS;
+    return fd;
 }
 
 
@@ -265,22 +268,22 @@ qemuOpenClientUNIX(virConnectPtr conn, c
  * connection closes.
  */
 static int qemuProcessRequest(virConnectPtr conn,
-                               virDomainPtr dom,
-                               struct qemud_packet *req,
-                               struct qemud_packet *reply) {
+                              int qemud_fd,
+                              virDomainPtr dom,
+                              struct qemud_packet *req,
+                              struct qemud_packet *reply) {
     char *out = (char *)req;
     int outDone = 0;
     int outLeft = sizeof(struct qemud_packet_header) + req->header.dataSize;
     char *in = (char *)reply;
     int inGot = 0;
     int inLeft = sizeof(struct qemud_packet_header);
-    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     /* printf("Send request %d\n", req->header.type); */
 
     /* Block sending entire outgoing packet */
     while (outLeft) {
-        int got = write(priv->qemud_fd, out+outDone, outLeft);
+        int got = write(qemud_fd, out+outDone, outLeft);
         if (got < 0) {
             return -1;
         }
@@ -290,7 +293,7 @@ static int qemuProcessRequest(virConnect
 
     /* Block waiting for header to come back */
     while (inLeft) {
-        int done = read(priv->qemud_fd, in+inGot, inLeft);
+        int done = read(qemud_fd, in+inGot, inLeft);
         if (done <= 0) {
             return -1;
         }
@@ -318,7 +321,7 @@ static int qemuProcessRequest(virConnect
     /* Now block reading in body */
     inLeft = reply->header.dataSize;
     while (inLeft) {
-        int done = read(priv->qemud_fd, in+inGot, inLeft);
+        int done = read(qemud_fd, in+inGot, inLeft);
         if (done <= 0) {
             return -1;
         }
@@ -411,17 +414,17 @@ static int qemuOpen(virConnectPtr conn,
         return VIR_DRV_OPEN_ERROR;
     }
 
-    priv->qemud_fd = -1;
-
     ret = qemuOpenConnection(conn, uri, flags & VIR_DRV_OPEN_RO ? 1 : 0);
     xmlFreeURI(uri);
 
-    if (priv->qemud_fd == -1 || ret < 0) {
+    if (ret < 0) {
         free (priv);
         conn->privateData = NULL;
         return VIR_DRV_OPEN_ERROR;
     }
 
+    priv->qemud_fd = ret;
+
     return VIR_DRV_OPEN_SUCCESS;
 }
 
@@ -446,11 +449,12 @@ qemuClose (virConnectPtr conn)
 static int qemuGetVersion(virConnectPtr conn,
                           unsigned long *hvVer) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_GET_VERSION;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -462,11 +466,12 @@ static int qemuGetVersion(virConnectPtr 
 static int qemuNodeGetInfo(virConnectPtr conn,
                            virNodeInfoPtr info) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_GET_NODEINFO;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -487,6 +492,7 @@ qemuGetCapabilities (virConnectPtr conn)
 {
     struct qemud_packet req, reply;
     char *xml;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     /* Punt the request across to the daemon, because the daemon
      * has tables describing available architectures.
@@ -494,7 +500,7 @@ qemuGetCapabilities (virConnectPtr conn)
     req.header.type = QEMUD_PKT_GET_CAPABILITIES;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -511,11 +517,12 @@ qemuGetCapabilities (virConnectPtr conn)
 
 static int qemuNumOfDomains(virConnectPtr conn) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_NUM_DOMAINS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -528,11 +535,12 @@ static int qemuListDomains(virConnectPtr
                            int maxids) {
     struct qemud_packet req, reply;
     int i, nDomains;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_LIST_DOMAINS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -554,6 +562,7 @@ qemuDomainCreateLinux(virConnectPtr conn
     struct qemud_packet req, reply;
     virDomainPtr dom;
     int len = strlen(xmlDesc);
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     if (len > (QEMUD_MAX_XML_LEN-1)) {
         return NULL;
@@ -564,7 +573,7 @@ qemuDomainCreateLinux(virConnectPtr conn
     strcpy(req.data.domainCreateRequest.xml, xmlDesc);
     req.data.domainCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -584,12 +593,13 @@ static virDomainPtr qemuLookupDomainByID
                                          int id) {
     struct qemud_packet req, reply;
     virDomainPtr dom;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_ID;
     req.header.dataSize = sizeof(req.data.domainLookupByIDRequest);
     req.data.domainLookupByIDRequest.id = id;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -609,12 +619,13 @@ static virDomainPtr qemuLookupDomainByUU
                                            const unsigned char *uuid) {
     struct qemud_packet req, reply;
     virDomainPtr dom;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_LOOKUP_BY_UUID;
     req.header.dataSize = sizeof(req.data.domainLookupByUUIDRequest);
     memmove(req.data.domainLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -634,6 +645,7 @@ static virDomainPtr qemuLookupDomainByNa
                                            const char *name) {
     struct qemud_packet req, reply;
     virDomainPtr dom;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     if (strlen(name) > (QEMUD_MAX_NAME_LEN-1))
         return NULL;
@@ -642,7 +654,7 @@ static virDomainPtr qemuLookupDomainByNa
     req.header.dataSize = sizeof(req.data.domainLookupByNameRequest);
     strcpy(req.data.domainLookupByNameRequest.name, name);
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -657,12 +669,13 @@ static virDomainPtr qemuLookupDomainByNa
 
 static int qemuDestroyDomain(virDomainPtr domain) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_DESTROY;
     req.header.dataSize = sizeof(req.data.domainDestroyRequest);
     req.data.domainDestroyRequest.id = domain->id;
 
-    if (qemuProcessRequest(domain->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -673,28 +686,30 @@ static int qemuShutdownDomain(virDomainP
     return qemuDestroyDomain(domain);
 }
 
-static int qemuResumeDomain(virDomainPtr domain ATTRIBUTE_UNUSED) {
+static int qemuResumeDomain(virDomainPtr domain) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_RESUME;
     req.header.dataSize = sizeof(req.data.domainResumeRequest);
     req.data.domainResumeRequest.id = domain->id;
 
-    if (qemuProcessRequest(domain->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
     return 0;
 }
 
-static int qemuPauseDomain(virDomainPtr domain ATTRIBUTE_UNUSED) {
+static int qemuPauseDomain(virDomainPtr domain) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_SUSPEND;
     req.header.dataSize = sizeof(req.data.domainSuspendRequest);
     req.data.domainSuspendRequest.id = domain->id;
 
-    if (qemuProcessRequest(domain->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -704,12 +719,13 @@ static int qemuPauseDomain(virDomainPtr 
 static int qemuGetDomainInfo(virDomainPtr domain,
                              virDomainInfoPtr info) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_GET_INFO;
     req.header.dataSize = sizeof(req.data.domainGetInfoRequest);
     memmove(req.data.domainGetInfoRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(domain->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -740,12 +756,13 @@ static int qemuGetDomainInfo(virDomainPt
 
 static char *qemuDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) domain->conn->privateData;
 
     req.header.type = QEMUD_PKT_DUMP_XML;
     req.header.dataSize = sizeof(req.data.domainDumpXMLRequest);
     memmove(req.data.domainDumpXMLRequest.uuid, domain->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(domain->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(domain->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -765,11 +782,12 @@ static int qemuRestoreDomain(virConnectP
 
 static int qemuNumOfDefinedDomains(virConnectPtr conn) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_NUM_DEFINED_DOMAINS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -781,11 +799,12 @@ static int qemuListDefinedDomains(virCon
                                   int maxnames){
     struct qemud_packet req, reply;
     int i, nDomains;
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     req.header.type = QEMUD_PKT_LIST_DEFINED_DOMAINS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -803,12 +822,13 @@ static int qemuListDefinedDomains(virCon
 
 static int qemuDomainCreate(virDomainPtr dom) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_START;
     req.header.dataSize = sizeof(req.data.domainStartRequest);
     memcpy(req.data.domainStartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(dom->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -821,6 +841,7 @@ static virDomainPtr qemuDomainDefineXML(
     struct qemud_packet req, reply;
     virDomainPtr dom;
     int len = strlen(xml);
+    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
 
     if (len > (QEMUD_MAX_XML_LEN-1)) {
         return NULL;
@@ -831,7 +852,7 @@ static virDomainPtr qemuDomainDefineXML(
     strcpy(req.data.domainDefineRequest.xml, xml);
     req.data.domainDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -849,12 +870,13 @@ static virDomainPtr qemuDomainDefineXML(
 static int qemuUndefine(virDomainPtr dom) {
     struct qemud_packet req, reply;
     int ret = 0;
+    qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_UNDEFINE;
     req.header.dataSize = sizeof(req.data.domainUndefineRequest);
     memcpy(req.data.domainUndefineRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(dom->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         ret = -1;
         goto cleanup;
     }
@@ -869,12 +891,13 @@ static int qemuUndefine(virDomainPtr dom
 static int qemuDomainGetAutostart(virDomainPtr dom,
                                   int *autostart) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_GET_AUTOSTART;
     req.header.dataSize = sizeof(req.data.domainGetAutostartRequest);
     memmove(req.data.domainGetAutostartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(dom->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -886,13 +909,14 @@ static int qemuDomainGetAutostart(virDom
 static int qemuDomainSetAutostart(virDomainPtr dom,
                                   int autostart) {
     struct qemud_packet req, reply;
+    qemuPrivatePtr priv = (qemuPrivatePtr) dom->conn->privateData;
 
     req.header.type = QEMUD_PKT_DOMAIN_SET_AUTOSTART;
     req.header.dataSize = sizeof(req.data.domainSetAutostartRequest);
     req.data.domainSetAutostartRequest.autostart = (autostart != 0);
     memmove(req.data.domainSetAutostartRequest.uuid, dom->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(dom->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(dom->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -900,48 +924,62 @@ static int qemuDomainSetAutostart(virDom
 }
 
 static int qemuNetworkOpen(virConnectPtr conn,
-                           const char *name,
+                           const char *name ATTRIBUTE_UNUSED,
                            int flags) {
-    xmlURIPtr uri = NULL;
-    int ret = -1;
-    qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
-
-    if (priv->qemud_fd != -1)
-        return VIR_DRV_OPEN_SUCCESS;
+    qemuNetworkPrivatePtr netpriv = NULL;
 
-    if (name)
-        uri = xmlParseURI(name);
-
-    if (uri && uri->scheme && !strcmp(uri->scheme, "qemu"))
-        ret = qemuOpen(conn, name, flags);
-    else if (geteuid() == 0)
-        ret = qemuOpen(conn, "qemu:///system", flags);
-    else
-        ret = qemuOpen(conn, "qemu:///session", flags);
+    if (!(netpriv = malloc(sizeof(struct _qemuNetworkPrivate)))) {
+        qemuError (conn, NULL, VIR_ERR_NO_MEMORY, __FUNCTION__);
+        return VIR_DRV_OPEN_ERROR;
+    }
 
-    if (uri)
+    if (!strcmp(conn->driver->name, "QEMU")) {
+        /* QEMU driver is active - just re-use existing connection */
+        qemuPrivatePtr priv = (qemuPrivatePtr) conn->privateData;
+        netpriv->qemud_fd = priv->qemud_fd;
+        netpriv->shared = 1;
+        conn->networkPrivateData = netpriv;
+        return 0;
+    } else {
+        /* Non-QEMU driver is active - open a new connection */
+        const char *drvname = geteuid() == 0 ? "qemu:///system" : "qemu://session";
+        xmlURIPtr uri = xmlParseURI(drvname);
+        int ret = qemuOpenConnection(conn, uri, flags & VIR_DRV_OPEN_RO ? 1 : 0);
         xmlFreeURI(uri);
 
-    return ret;
+        if (ret < 0) {
+            free(netpriv);
+            return ret;
+        } else {
+            netpriv->qemud_fd = ret;
+            netpriv->shared = 0;
+            conn->networkPrivateData = netpriv;
+            return 0;
+        }
+    }
 }
 
 static int
-qemuNetworkClose (virConnectPtr conn ATTRIBUTE_UNUSED)
+qemuNetworkClose (virConnectPtr conn)
 {
-    /* NB: This will fail to close the connection properly
-     * qemuRegister is changed so that it only registers the
-     * network (not the connection driver).
-     */
+    qemuNetworkPrivatePtr netpriv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
+
+    if (!netpriv->shared)
+        close(netpriv->qemud_fd);
+    free(netpriv);
+    conn->networkPrivateData = NULL;
+
     return 0;
 }
 
 static int qemuNumOfNetworks(virConnectPtr conn) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NUM_NETWORKS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -953,11 +991,12 @@ static int qemuListNetworks(virConnectPt
                             int maxnames) {
     struct qemud_packet req, reply;
     int i, nNetworks;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_LIST_NETWORKS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -975,11 +1014,12 @@ static int qemuListNetworks(virConnectPt
 
 static int qemuNumOfDefinedNetworks(virConnectPtr conn) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NUM_DEFINED_NETWORKS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -991,11 +1031,12 @@ static int qemuListDefinedNetworks(virCo
                                    int maxnames) {
     struct qemud_packet req, reply;
     int i, nNetworks;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_LIST_DEFINED_NETWORKS;
     req.header.dataSize = 0;
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -1015,12 +1056,13 @@ static virNetworkPtr qemuNetworkLookupBy
                                              const unsigned char *uuid) {
     struct qemud_packet req, reply;
     virNetworkPtr network;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_LOOKUP_BY_UUID;
     req.header.dataSize = sizeof(req.data.networkLookupByUUIDRequest);
     memmove(req.data.networkLookupByUUIDRequest.uuid, uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1038,6 +1080,7 @@ static virNetworkPtr qemuNetworkLookupBy
                                              const char *name) {
     struct qemud_packet req, reply;
     virNetworkPtr network;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     if (strlen(name) > (QEMUD_MAX_NAME_LEN-1))
         return NULL;
@@ -1046,7 +1089,7 @@ static virNetworkPtr qemuNetworkLookupBy
     req.header.dataSize = sizeof(req.data.networkLookupByNameRequest);
     strcpy(req.data.networkLookupByNameRequest.name, name);
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1063,6 +1106,7 @@ static virNetworkPtr qemuNetworkCreateXM
     struct qemud_packet req, reply;
     virNetworkPtr network;
     int len = strlen(xmlDesc);
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     if (len > (QEMUD_MAX_XML_LEN-1)) {
         return NULL;
@@ -1073,7 +1117,7 @@ static virNetworkPtr qemuNetworkCreateXM
     strcpy(req.data.networkCreateRequest.xml, xmlDesc);
     req.data.networkCreateRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1093,6 +1137,7 @@ static virNetworkPtr qemuNetworkDefineXM
     struct qemud_packet req, reply;
     virNetworkPtr network;
     int len = strlen(xml);
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) conn->networkPrivateData;
 
     if (len > (QEMUD_MAX_XML_LEN-1)) {
         return NULL;
@@ -1103,7 +1148,7 @@ static virNetworkPtr qemuNetworkDefineXM
     strcpy(req.data.networkDefineRequest.xml, xml);
     req.data.networkDefineRequest.xml[QEMUD_MAX_XML_LEN-1] = '\0';
 
-    if (qemuProcessRequest(conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1120,12 +1165,13 @@ static virNetworkPtr qemuNetworkDefineXM
 static int qemuNetworkUndefine(virNetworkPtr network) {
     struct qemud_packet req, reply;
     int ret = 0;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_UNDEFINE;
     req.header.dataSize = sizeof(req.data.networkUndefineRequest);
     memcpy(req.data.networkUndefineRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         ret = -1;
         goto cleanup;
     }
@@ -1139,12 +1185,13 @@ static int qemuNetworkUndefine(virNetwor
 
 static int qemuNetworkCreate(virNetworkPtr network) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_START;
     req.header.dataSize = sizeof(req.data.networkStartRequest);
     memcpy(req.data.networkStartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -1153,12 +1200,13 @@ static int qemuNetworkCreate(virNetworkP
 
 static int qemuNetworkDestroy(virNetworkPtr network) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_DESTROY;
     req.header.dataSize = sizeof(req.data.networkDestroyRequest);
     memcpy(req.data.networkDestroyRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -1167,12 +1215,13 @@ static int qemuNetworkDestroy(virNetwork
 
 static char * qemuNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_DUMP_XML;
     req.header.dataSize = sizeof(req.data.networkDumpXMLRequest);
     memmove(req.data.networkDumpXMLRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1183,12 +1232,13 @@ static char * qemuNetworkDumpXML(virNetw
 
 static char * qemuNetworkGetBridgeName(virNetworkPtr network) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_GET_BRIDGE_NAME;
     req.header.dataSize = sizeof(req.data.networkGetBridgeNameRequest);
     memmove(req.data.networkGetBridgeNameRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return NULL;
     }
 
@@ -1200,12 +1250,13 @@ static char * qemuNetworkGetBridgeName(v
 static int qemuNetworkGetAutostart(virNetworkPtr network,
                                    int *autostart) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_GET_AUTOSTART;
     req.header.dataSize = sizeof(req.data.networkGetAutostartRequest);
     memmove(req.data.networkGetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
@@ -1217,13 +1268,14 @@ static int qemuNetworkGetAutostart(virNe
 static int qemuNetworkSetAutostart(virNetworkPtr network,
                                    int autostart) {
     struct qemud_packet req, reply;
+    qemuNetworkPrivatePtr priv = (qemuNetworkPrivatePtr) network->conn->networkPrivateData;
 
     req.header.type = QEMUD_PKT_NETWORK_SET_AUTOSTART;
     req.header.dataSize = sizeof(req.data.networkSetAutostartRequest);
     req.data.networkSetAutostartRequest.autostart = (autostart != 0);
     memmove(req.data.networkSetAutostartRequest.uuid, network->uuid, QEMUD_UUID_RAW_LEN);
 
-    if (qemuProcessRequest(network->conn, NULL, &req, &reply) < 0) {
+    if (qemuProcessRequest(network->conn, priv->qemud_fd, NULL, &req, &reply) < 0) {
         return -1;
     }
 
diff -rup libvirt-pristine/src/xen_unified.c libvirt/src/xen_unified.c
--- libvirt-pristine/src/xen_unified.c	2007-04-02 11:42:10.000000000 -0400
+++ libvirt/src/xen_unified.c	2007-04-02 12:03:05.000000000 -0400
@@ -26,6 +26,8 @@
  */
 
 #include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include <xen/dom0_ops.h>
 
 #include "internal.h"
@@ -107,19 +109,22 @@ xenUnifiedOpen (virConnectPtr conn, cons
   priv->xshandle = NULL;
   priv->proxy = -1;
 
-  /* All Xen drivers should open OK, except that the proxy is allowed
-   * to fail.
-   */
   for (i = 0; i < nb_drivers; ++i) {
     int failed_to_open = 1;
 
+    /* Ignore proxy for root */
+    if (i == proxy_offset && getuid() == 0)
+      continue;
+
     if (drivers[i]->open &&
 	drivers[i]->open (conn, name, flags) == VIR_DRV_OPEN_SUCCESS)
       failed_to_open = 0;
 
-    if (failed_to_open && i != proxy_offset) {
+    /* If as root, then all drivers must succeed.
+       If non-root, then only proxy must succeed */
+    if (failed_to_open && (getuid() == 0 || i == proxy_offset)) {
       for (j = 0; j < i; ++j)
-	drivers[j]->close (conn);
+	  drivers[j]->close (conn);
       return VIR_DRV_OPEN_ERROR;
     }
   }
diff -rup libvirt-pristine/proxy/libvirt_proxy.c libvirt/proxy/libvirt_proxy.c
--- libvirt-pristine/proxy/libvirt_proxy.c	2007-03-21 09:46:34.000000000 -0400
+++ libvirt/proxy/libvirt_proxy.c	2007-04-02 12:01:55.000000000 -0400
@@ -25,6 +25,7 @@
 #include "xen_internal.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
+#include "xen_unified.h"
 
 static int fdServer = -1;
 static int debug = 0;
@@ -58,6 +59,23 @@ static int
 proxyInitXen(void) {
     int ret;
     unsigned long xenVersion2;
+    xenUnifiedPrivatePtr priv;
+
+    /* Allocate per-connection private data. */
+    priv = malloc (sizeof *priv);
+    if (!priv) {
+        fprintf(stderr, "Failed to allocate private data\n");
+        return(-1);
+    }
+    conn->privateData = priv;
+
+    priv->handle = -1;
+    priv->xendConfigVersion = -1;
+    priv->type = -1;
+    priv->len = -1;
+    priv->addr = NULL;
+    priv->xshandle = NULL;
+    priv->proxy = -1;
 
     ret = xenHypervisorOpen(conn, NULL, VIR_DRV_OPEN_QUIET);
     if (ret < 0) {


More information about the libvir-list mailing list