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 -=|
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) {