[libvirt] [PATCH] Always close drivers when a virConnectPtr is released
by Matthias Bolte
virConnectClose calls virUnrefConnect which in turn closes
all open drivers when the refcount of that connection dropped
to zero. This works fine when you free all other objects that
hold a ref to the connection before you close it, because in
this case virUnrefConnect is the one that removes the last
ref to the connection.
But it doesn't work when you close the connection first before
freeing the other objects. This is because the other virUnref*
functions call virReleaseConnect when they detect that the
connection's refcount dropped to zero. In this case another
virUnref* function (different from virUnrefConnect) removes the
last ref to the connection. This results in not closing the
open drivers and leaking things that should have been cleaned
up in the driver close functions.
To fix this move the driver close calls to virReleaseConnect.
---
src/datatypes.c | 47 +++++++++++++++++++++++------------------------
1 files changed, 23 insertions(+), 24 deletions(-)
diff --git a/src/datatypes.c b/src/datatypes.c
index 46009ae..9817538 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -247,6 +247,29 @@ failed:
static void
virReleaseConnect(virConnectPtr conn) {
DEBUG("release connection %p", conn);
+
+ /* make sure to release the connection lock before we call the
+ * close() callbacks, otherwise we will deadlock if an error
+ * is raised by any of the callbacks */
+ virMutexUnlock(&conn->lock);
+
+ if (conn->networkDriver)
+ conn->networkDriver->close (conn);
+ if (conn->interfaceDriver)
+ conn->interfaceDriver->close (conn);
+ if (conn->storageDriver)
+ conn->storageDriver->close (conn);
+ if (conn->deviceMonitor)
+ conn->deviceMonitor->close (conn);
+ if (conn->secretDriver)
+ conn->secretDriver->close (conn);
+ if (conn->nwfilterDriver)
+ conn->nwfilterDriver->close (conn);
+ if (conn->driver)
+ conn->driver->close (conn);
+
+ virMutexLock(&conn->lock);
+
if (conn->domains != NULL)
virHashFree(conn->domains, (virHashDeallocator) virDomainFreeName);
if (conn->networks != NULL)
@@ -295,30 +318,6 @@ virUnrefConnect(virConnectPtr conn) {
conn->refs--;
refs = conn->refs;
if (refs == 0) {
- /* make sure to release the connection lock before we call the
- * close() callbacks, otherwise we will deadlock if an error
- * is raised by any of the callbacks
- */
- virMutexUnlock(&conn->lock);
- if (conn->networkDriver)
- conn->networkDriver->close (conn);
- if (conn->interfaceDriver)
- conn->interfaceDriver->close (conn);
- if (conn->storageDriver)
- conn->storageDriver->close (conn);
- if (conn->deviceMonitor)
- conn->deviceMonitor->close (conn);
- if (conn->secretDriver)
- conn->secretDriver->close (conn);
- if (conn->nwfilterDriver)
- conn->nwfilterDriver->close (conn);
- if (conn->driver)
- conn->driver->close (conn);
-
- /* reacquire the connection lock since virReleaseConnect expects
- * it to already be held
- */
- virMutexLock(&conn->lock);
virReleaseConnect(conn);
/* Already unlocked mutex */
return (0);
--
1.7.0.4
14 years
[libvirt] ruby-libvirt issue
by Jaromír Červenka
Good evening,
could anybody explain me this, please?
divinus:~ # virsh
error: cannot recv data: : Connection reset by peer
error: failed to connect to the hypervisor
divinus:~ #
I am trying to imlement Chris's ruby-libvirt to my Ruby on Rails
application. First few connection to libvirt daemon (thru ruby-libvirt API)
from my app are ok, but then somethings happend and it's not possible to
connect anymore until I restart libvirt daemon manually by init.d script or
until I restart apache (or WEBrick). And it's not possible connect to virsh
from shell also! See messages above.
When I try ruby-libvirt from bare Ruby script, everythig is fine - doesn't
matter how many times I connect. It's strange.
Does anybody have experience with ruby-libvirt in RoR application?
Thank you.
Jaromir.
14 years
[libvirt] [PATCH] Fix memory leaks in audit & VirtualBox code
by Daniel P. Berrange
* src/util/virtaudit.c: Free audit string
* src/vbox/vbox_XPCOMCGlue.c: Free library name
---
src/util/virtaudit.c | 6 +++++-
src/vbox/vbox_XPCOMCGlue.c | 1 +
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/src/util/virtaudit.c b/src/util/virtaudit.c
index b630fce..33be4d9 100644
--- a/src/util/virtaudit.c
+++ b/src/util/virtaudit.c
@@ -32,6 +32,7 @@
#include "virtaudit.h"
#include "util.h"
#include "files.h"
+#include "memory.h"
/* Provide the macros in case the header file is old.
FIXME: should be removed. */
@@ -110,8 +111,10 @@ void virAuditSend(const char *file ATTRIBUTE_UNUSED, const char *func,
}
#if HAVE_AUDIT
- if (auditfd < 0)
+ if (auditfd < 0) {
+ VIR_FREE(str);
return;
+ }
if (str) {
static const int record_types[] = {
@@ -128,6 +131,7 @@ void virAuditSend(const char *file ATTRIBUTE_UNUSED, const char *func,
VIR_WARN("Failed to send audit message %s: %s",
NULLSTR(str), virStrerror(errno, ebuf, sizeof ebuf));
}
+ VIR_FREE(str);
}
#endif
}
diff --git a/src/vbox/vbox_XPCOMCGlue.c b/src/vbox/vbox_XPCOMCGlue.c
index 15a9622..d73e799 100644
--- a/src/vbox/vbox_XPCOMCGlue.c
+++ b/src/vbox/vbox_XPCOMCGlue.c
@@ -98,6 +98,7 @@ static int tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing)
VIR_ERROR(_("Libaray '%s' doesn't exist"), name);
}
+ VIR_FREE(name);
return -1;
}
} else {
--
1.7.2.3
14 years
[libvirt] [PATCH] 802.1Qbg: use pre-associate state at beginning of incoming migration
by Stefan Berger
This patch introduces the usage of the pre-associate state of the IEEE
802.1Qbg standard on incoming VM migration on the target host. It is in
response to bugzilla entry 632750.
https://bugzilla.redhat.com/show_bug.cgi?id=632750
For being able to differentiate the exact reason as to why a macvtap
device is being created, either due to a VM creation or an incoming VM
migration, I needed to pass that reason as a parameter from wherever
qemudStartVMDaemon is being called in order to determine whether to send
an ASSOCIATE (VM creation) or a PRE-ASSOCIATE (incoming VM migration)
towards lldpad.
I am also fixing problem with the virsh domainxml-to-native call on the way.
Gerhard successfully tested the patch with a recent blade network
802.1Qbg-compliant switch.
The patch should not have any side-effects on the 802.1Qbh support in
libvirt, but Scott (cc'ed) may want to verify this.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
Signed-off-by: Gerhard Stenzel <gerhard.stenzel(a)de.ibm.com>
---
src/libvirt_macvtap.syms | 2 +
src/qemu/qemu_conf.c | 12 +++++--
src/qemu/qemu_conf.h | 7 +++-
src/qemu/qemu_driver.c | 72 +++++++++++++++++++++++++++++++++++++----------
src/util/macvtap.c | 54 ++++++++++++++++++++++++++++++-----
src/util/macvtap.h | 20 +++++++++++--
6 files changed, 137 insertions(+), 30 deletions(-)
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1640,7 +1640,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
struct qemud_driver *driver,
virDomainNetDefPtr net,
unsigned long long qemuCmdFlags,
- const unsigned char *vmuuid)
+ const unsigned char *vmuuid,
+ enum vmOperation vmop)
{
int rc;
#if WITH_MACVTAP
@@ -1654,7 +1655,8 @@ qemudPhysIfaceConnect(virConnectPtr conn
rc = openMacvtapTap(net->ifname, net->mac, net->data.direct.linkdev,
net->data.direct.mode, vnet_hdr, vmuuid,
-&net->data.direct.virtPortProfile,&res_ifname);
+&net->data.direct.virtPortProfile,&res_ifname,
+ vmop);
if (rc>= 0) {
VIR_FREE(net->ifname);
net->ifname = res_ifname;
@@ -3951,7 +3953,8 @@ int qemudBuildCommandLine(virConnectPtr
int **vmfds,
int *nvmfds,
const char *migrateFrom,
- virDomainSnapshotObjPtr current_snapshot)
+ virDomainSnapshotObjPtr current_snapshot,
+ enum vmOperation vmop)
{
int i;
char memory[50];
@@ -4794,7 +4797,8 @@ int qemudBuildCommandLine(virConnectPtr
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
int tapfd = qemudPhysIfaceConnect(conn, driver, net,
qemuCmdFlags,
- def->uuid);
+ def->uuid,
+ vmop);
if (tapfd< 0)
goto error;
Index: libvirt-acl/src/qemu/qemu_conf.h
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.h
+++ libvirt-acl/src/qemu/qemu_conf.h
@@ -40,6 +40,7 @@
# include "cpu_conf.h"
# include "driver.h"
# include "bitmap.h"
+# include "macvtap.h"
# define qemudDebug(fmt, ...) do {} while(0)
@@ -238,7 +239,8 @@ int qemudBuildCommandLine
int **vmfds,
int *nvmfds,
const char *migrateFrom,
- virDomainSnapshotObjPtr current_snapshot)
+ virDomainSnapshotObjPtr current_snapshot,
+ enum vmOperation vmop)
ATTRIBUTE_NONNULL(1);
/* With vlan == -1, use netdev syntax, else old hostnet */
@@ -317,7 +319,8 @@ int qemudPhysIfaceConnect(virConnectPtr
struct qemud_driver *driver,
virDomainNetDefPtr net,
unsigned long long qemuCmdFlags,
- const unsigned char *vmuuid);
+ const unsigned char *vmuuid,
+ enum vmOperation vmop);
int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr **machines,
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -163,7 +163,8 @@ static int qemudStartVMDaemon(virConnect
const char *migrateFrom,
bool start_paused,
int stdin_fd,
- const char *stdin_path);
+ const char *stdin_path,
+ enum vmOperation vmop);
static void qemudShutdownVMDaemon(struct qemud_driver *driver,
virDomainObjPtr vm,
@@ -3864,7 +3865,8 @@ static int qemudStartVMDaemon(virConnect
const char *migrateFrom,
bool start_paused,
int stdin_fd,
- const char *stdin_path) {
+ const char *stdin_path,
+ enum vmOperation vmop) {
const char **argv = NULL, **tmp;
const char **progenv = NULL;
int i, ret, runflags;
@@ -4065,7 +4067,7 @@ static int qemudStartVMDaemon(virConnect
if (qemudBuildCommandLine(conn, driver, vm->def, priv->monConfig,
priv->monJSON, qemuCmdFlags,&argv,&progenv,
&vmfds,&nvmfds, migrateFrom,
- vm->current_snapshot)< 0)
+ vm->current_snapshot, vmop)< 0)
goto cleanup;
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir)< 0)
@@ -4854,7 +4856,7 @@ static virDomainPtr qemudDomainCreate(vi
if (qemudStartVMDaemon(conn, driver, vm, NULL,
(flags& VIR_DOMAIN_START_PAUSED) != 0,
- -1, NULL)< 0) {
+ -1, NULL, VM_OP_CREATE)< 0) {
qemuDomainStartAudit(vm, "booted", false);
if (qemuDomainObjEndJob(vm)> 0)
virDomainRemoveInactive(&driver->domains,
@@ -6997,7 +6999,8 @@ qemudDomainSaveImageStartVM(virConnectPt
}
/* Set the migration source and start it up. */
- ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path);
+ ret = qemudStartVMDaemon(conn, driver, vm, "stdio", true, fd, path,
+ VM_OP_RESTORE);
if (intermediate_pid != -1) {
/* Wait for intermediate process to exit */
@@ -7316,14 +7319,15 @@ static char *qemuDomainXMLToNative(virCo
if (!def)
goto cleanup;
- /* Since we're just exporting args, we can't do bridge/network
- * setups, since libvirt will normally create TAP devices
+ /* Since we're just exporting args, we can't do bridge/network/direct
+ * setups, since libvirt will normally create TAP/macvtap devices
* directly. We convert those configs into generic 'ethernet'
* config and assume the user has suitable 'ifup-qemu' scripts
*/
for (i = 0 ; i< def->nnets ; i++) {
virDomainNetDefPtr net = def->nets[i];
- if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
VIR_FREE(net->data.network.name);
memset(net, 0, sizeof *net);
@@ -7379,7 +7383,8 @@ static char *qemuDomainXMLToNative(virCo
&monConfig, 0, qemuCmdFlags,
&retargv,&retenv,
NULL, NULL, /* Don't want it to create TAP devices */
- NULL, NULL)< 0) {
+ NULL, NULL,
+ VM_OP_NO_OP)< 0) {
goto cleanup;
}
@@ -7466,7 +7471,8 @@ static int qemudDomainObjStart(virConnec
goto cleanup;
}
- ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1, NULL);
+ ret = qemudStartVMDaemon(conn, driver, vm, NULL, start_paused, -1, NULL,
+ VM_OP_CREATE);
qemuDomainStartAudit(vm, "booted", ret>= 0);
if (ret>= 0) {
virDomainEventPtr event =
@@ -8309,7 +8315,8 @@ static int qemudDomainAttachNetDevice(vi
if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
qemuCmdFlags,
- vm->def->uuid))< 0)
+ vm->def->uuid,
+ VM_OP_CREATE))< 0)
return -1;
}
@@ -10983,7 +10990,7 @@ qemudDomainMigratePrepareTunnel(virConne
* -incoming unix:/path/to/file or exec:nc -U /path/to/file
*/
internalret = qemudStartVMDaemon(dconn, driver, vm, migrateFrom, true,
- -1, NULL);
+ -1, NULL, VM_OP_MIGRATE_IN_START);
VIR_FREE(migrateFrom);
if (internalret< 0) {
qemuDomainStartAudit(vm, "migrated", false);
@@ -11229,7 +11236,7 @@ qemudDomainMigratePrepare2 (virConnectPt
*/
snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port);
if (qemudStartVMDaemon (dconn, driver, vm, migrateFrom, true,
- -1, NULL)< 0) {
+ -1, NULL, VM_OP_MIGRATE_IN_START)< 0) {
qemuDomainStartAudit(vm, "migrated", false);
/* Note that we don't set an error here because qemudStartVMDaemon
* should have already done that.
@@ -11844,6 +11851,41 @@ cleanup:
return ret;
}
+static void
+qemudVPAssociatePortProfiles(virDomainDefPtr def) {
+ int i;
+ int last_good_net = -1;
+ virDomainNetDefPtr net;
+
+ for (i = 0; i< def->nnets; i++) {
+ net = def->nets[i];
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ if (vpAssociatePortProfileId(net->ifname,
+ net->mac,
+ net->data.direct.linkdev,
+&net->data.direct.virtPortProfile,
+ def->uuid,
+ VM_OP_MIGRATE_IN_FINISH) != 0)
+ goto err_exit;
+ }
+ last_good_net = i;
+ }
+
+ return;
+
+err_exit:
+ for (i = 0; i< last_good_net; i++) {
+ net = def->nets[i];
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ vpDisassociatePortProfileId(net->ifname,
+ net->mac,
+ net->data.direct.linkdev,
+&net->data.direct.virtPortProfile,
+ VM_OP_MIGRATE_IN_FINISH);
+ }
+ }
+}
+
/* Finish is the third and final step, and it runs on the destination host. */
static virDomainPtr
qemudDomainMigrateFinish2 (virConnectPtr dconn,
@@ -11904,6 +11946,8 @@ qemudDomainMigrateFinish2 (virConnectPtr
goto cleanup;
}
+ qemudVPAssociatePortProfiles(vm->def);
+
if (flags& VIR_MIGRATE_PERSIST_DEST) {
if (vm->persistent)
newVM = 0;
@@ -12796,7 +12840,7 @@ static int qemuDomainRevertToSnapshot(vi
goto endjob;
rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL,
- false, -1, NULL);
+ false, -1, NULL, VM_OP_CREATE);
qemuDomainStartAudit(vm, "from-snapshot", rc>= 0);
if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir)< 0)
goto endjob;
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -77,9 +77,22 @@
# define LLDPAD_PID_FILE "/var/run/lldpad.pid"
+static const char *vmOpStr[] = {
+ [VM_OP_CREATE] = "create",
+ [VM_OP_SAVE] = "save",
+ [VM_OP_RESTORE] = "restore",
+ [VM_OP_DESTROY] = "destroy",
+ [VM_OP_MIGRATE_OUT] = "migrate out",
+ [VM_OP_MIGRATE_IN_START] = "migrate in start",
+ [VM_OP_MIGRATE_IN_FINISH] = "migrate in finish",
+ [VM_OP_NO_OP] = "no-op"
+};
+
+
enum virVirtualPortOp {
ASSOCIATE = 0x1,
DISASSOCIATE = 0x2,
+ PREASSOCIATE = 0x3,
};
@@ -551,7 +564,8 @@ openMacvtapTap(const char *tgifname,
int vnet_hdr,
const unsigned char *vmuuid,
virVirtualPortProfileParamsPtr virtPortProfile,
- char **res_ifname)
+ char **res_ifname,
+ enum vmOperation vmOp)
{
const char *type = "macvtap";
int c, rc;
@@ -563,6 +577,8 @@ openMacvtapTap(const char *tgifname,
*res_ifname = NULL;
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, vmOpStr[vmOp]);
+
if (tgifname) {
if(ifaceGetIndex(false, tgifname,&ifindex) == 0) {
if (STRPREFIX(tgifname,
@@ -601,7 +617,7 @@ create_name:
macaddress,
linkdev,
virtPortProfile,
- vmuuid) != 0) {
+ vmuuid, vmOp) != 0) {
rc = -1;
goto link_del_exit;
}
@@ -634,7 +650,8 @@ disassociate_exit:
vpDisassociatePortProfileId(cr_ifname,
macaddress,
linkdev,
- virtPortProfile);
+ virtPortProfile,
+ vmOp);
link_del_exit:
link_del(cr_ifname);
@@ -662,7 +679,8 @@ delMacvtap(const char *ifname,
if (ifname) {
vpDisassociatePortProfileId(ifname, macaddr,
linkdev,
- virtPortProfile);
+ virtPortProfile,
+ VM_OP_DESTROY);
link_del(ifname);
}
}
@@ -1320,6 +1338,9 @@ doPortProfileOp8021Qbg(const char *ifnam
portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
switch (virtPortOp) {
+ case PREASSOCIATE:
+ op = PORT_REQUEST_PREASSOCIATE;
+ break;
case ASSOCIATE:
op = PORT_REQUEST_ASSOCIATE;
break;
@@ -1484,6 +1505,7 @@ err_exit:
* @macvtap_ifname: The name of the macvtap device
* @virtPort: pointer to the object holding port profile parameters
* @vmuuid : the UUID of the virtual machine
+ * @vmOp : The VM operation (i.e., create, no-op)
*
* Associate a port on a swtich with a profile. This function
* may notify a kernel driver or an external daemon to run
@@ -1499,13 +1521,19 @@ vpAssociatePortProfileId(const char *mac
const unsigned char *macvtap_macaddr,
const char *linkdev,
const virVirtualPortProfileParamsPtr virtPort,
- const unsigned char *vmuuid)
+ const unsigned char *vmuuid,
+ enum vmOperation vmOp)
{
int rc = 0;
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
virtPort, macvtap_ifname);
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, vmOpStr[vmOp]);
+
+ if (vmOp == VM_OP_NO_OP)
+ return 0;
+
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
case VIR_VIRTUALPORT_TYPE_LAST:
@@ -1513,10 +1541,16 @@ vpAssociatePortProfileId(const char *mac
case VIR_VIRTUALPORT_8021QBG:
rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
- virtPort, ASSOCIATE);
+ virtPort,
+ (vmOp == VM_OP_MIGRATE_IN_START)
+ ? PREASSOCIATE
+ : ASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
+ /* avoid associating twice */
+ if (vmOp == VM_OP_MIGRATE_IN_FINISH)
+ break;
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
vmuuid,
ASSOCIATE);
@@ -1542,13 +1576,16 @@ int
vpDisassociatePortProfileId(const char *macvtap_ifname,
const unsigned char *macvtap_macaddr,
const char *linkdev,
- const virVirtualPortProfileParamsPtr virtPort)
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum vmOperation vmOp)
{
int rc = 0;
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
virtPort, macvtap_ifname);
+ VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, vmOpStr[vmOp]);
+
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
case VIR_VIRTUALPORT_TYPE_LAST:
@@ -1560,6 +1597,9 @@ vpDisassociatePortProfileId(const char *
break;
case VIR_VIRTUALPORT_8021QBH:
+ /* avoid disassociating twice */
+ if (vmOp == VM_OP_MIGRATE_IN_FINISH)
+ break;
rc = doPortProfileOp8021Qbh(linkdev, virtPort,
NULL,
DISASSOCIATE);
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -62,6 +62,17 @@ struct _virVirtualPortProfileParams {
# include "internal.h"
+enum vmOperation {
+ VM_OP_CREATE,
+ VM_OP_SAVE,
+ VM_OP_RESTORE,
+ VM_OP_DESTROY,
+ VM_OP_MIGRATE_OUT,
+ VM_OP_MIGRATE_IN_START,
+ VM_OP_MIGRATE_IN_FINISH,
+ VM_OP_NO_OP,
+};
+
int openMacvtapTap(const char *ifname,
const unsigned char *macaddress,
const char *linkdev,
@@ -69,7 +80,8 @@ int openMacvtapTap(const char *ifname,
int vnet_hdr,
const unsigned char *vmuuid,
virVirtualPortProfileParamsPtr virtPortProfile,
- char **res_ifname);
+ char **res_ifname,
+ enum vmOperation vmop);
void delMacvtap(const char *ifname,
const unsigned char *macaddress,
@@ -86,12 +98,14 @@ int vpAssociatePortProfileId(const char
const unsigned char *macvtap_macaddr,
const char *linkdev,
const virVirtualPortProfileParamsPtr virtPort,
- const unsigned char *vmuuid);
+ const unsigned char *vmuuid,
+ enum vmOperation vmOp);
int vpDisassociatePortProfileId(const char *macvtap_ifname,
const unsigned char *macvtap_macaddr,
const char *linkdev,
- const virVirtualPortProfileParamsPtr virtPort);
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum vmOperation vmOp);
VIR_ENUM_DECL(virVirtualPort)
Index: libvirt-acl/src/libvirt_macvtap.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_macvtap.syms
+++ libvirt-acl/src/libvirt_macvtap.syms
@@ -3,3 +3,5 @@
# macvtap.h
openMacvtapTap;
delMacvtap;
+vpAssociatePortProfileId;
+vpDisassociatePortProfileId;
14 years
[libvirt] RFC: add new API to known if domain has been updated
by Osier Yang
Hi, all
Suppose that one updated a domain, and want to restart the
domain with original configuration.
However, currently, unless shutdown the domain first, and then
restart or reload libvirtd, otherwise domain will still be started
with changed configuration. e.g.
# virsh list --all
Id Name State
----------------------------------
1 f14 running
# virsh dumpxml f14 | grep -A 7 cdrom
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/cd1.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<alias name='ide0-1-0'/>
<address type='drive' controller='0' bus='1' unit='0'/>
</disk>
# virsh update-device f14 cd2.xml
# virsh dumpxml f14 | grep -A 7 cdrom
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/cd2.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<alias name='ide0-1-0'/>
<address type='drive' controller='0' bus='1' unit='0'/>
</disk>
# virsh destroy f14
# virsh start f14
# virsh dumpxml f14 | grep -A 7 cdrom
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/var/lib/libvirt/images/cd2.iso'/>
<target dev='hdc' bus='ide'/>
<readonly/>
<alias name='ide0-1-0'/>
<address type='drive' controller='0' bus='1' unit='0'/>
</disk>
it's caused by libvirtd doesn't known if a domain is updated or not,
it updated the domain configuration in memory, but client could
not known about it.
As a result, one wants to start the domain with original configuration,
he has to shutdown the domain first, and then restart libvirt.
It will be better if client could known if the domain is updated
or not, and could choose to start the domain with original
configuration or the updated one.
So, considered introducing a new member, the idea is adding
"unsigned int updated :1;" for "virDomainObj", adn the functions which
will update domain configuration should set it to "1" so that
libvirtd could known the domain is updated. e.g.
static int qemudDomainChangeEjectableMedia (....)
{
.................
/* if Media is changed or ejected successfully */
if (!vm->updated)
vm->updated = 1;
..................
}
And the client such as virsh could provide optional parameter for user
to choose if start the guest with original configuration or not. e.g.
# virsh start f14 --original
it tells "virsh" to start the domain with the persistent domain
configuration "/etc/libvirt/qemu/$domain.xml" but not the updated
one maitained by libvirtd.
PS: if this API is introduced finnally, we can also add "updated"
information in "dominfo".
What do you think about it? patches are coming following this thread.
awaiting feedback.. :-)
- Osier
14 years
[libvirt] changing disk/usb stick content
by Roberto Attias (rattias)
Hello,
This is a request to extend libvirt documentation, explaining how is it
possible to change a floppy/CDROM/usb-stick content for a running VM
from host.
The VirDomainUpdateDeviceFlags function documentation states:
virDomainUpdateDeviceFlags
int virDomainUpdateDeviceFlags (virDomainPtr
<http://libvirt.org/html/libvirt-libvirt.html#virDomainPtr> domain,
const char * xml,
unsigned int flags)
Change a virtual device on a domain, using the flags parameter to
control how the device is changed. VIR_DOMAIN_DEVICE_MODIFY_CURRENT
specifies that the device change is made based on current domain
state.VIR_DOMAIN_DEVICE_MODIFY_LIVE
<http://libvirt.org/html/libvirt-libvirt.html#VIR_DOMAIN_DEVICE_MODIFY_L
IVE> specifies that the device shall be changed on the active domain
instance only and is not added to the persisted domain configuration.
VIR_DOMAIN_DEVICE_MODIFY_CONFIG specifies that the device shall be
changed on the persisted domain configuration only. Note that the target
hypervisor must return an error if unable to satisfy flags. E.g. the
hypervisor driver will return failure if LIVE is specified but it only
supports modifying the persisted device allocation. This method is used
for actions such changing CDROM/Floppy device media, altering the
graphics configuration such as password, reconfiguring the NIC device
backend connectivity, etc.
It would be really nice if you could provide an example of usage of this
command. Thanks to eblake on #virt who pointed me to this:
https://www.redhat.com/archives/libvir-list/2010-June/msg00219.html
You could easily extract an example of use from there.
Thanks,
Roberto
14 years
[libvirt] [PATCH] maint: sort exports
by Eric Blake
* src/libvirt_private.syms (buf.h): Sort.
---
Pushing under the trivial rule.
src/libvirt_private.syms | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0547cdf..33e52e2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -23,8 +23,8 @@ virBufferAdd;
virBufferAddChar;
virBufferContentAndReset;
virBufferError;
-virBufferEscapeString;
virBufferEscapeSexpr;
+virBufferEscapeString;
virBufferFreeAndReset;
virBufferStrcat;
virBufferURIEncodeString;
--
1.7.3.2
14 years
[libvirt] [PATCH] Don't log client errors in libvirtd
by Matthias Bolte
This reverts commit
Log all errors at level INFO to stop polluting syslog
04bd0360f32ec628ecf7943b3fd1468d6eb2dde5.
and makes virRaiseErrorFull() only log errors when not inside
libvirtd. This stops libvirtd from polluting it's own log with
client errors that'll be reported and logged on the client
side anyway.
---
daemon/libvirtd.c | 2 ++
src/libvirt_private.syms | 2 ++
src/util/logging.c | 14 ++++++++++++++
src/util/logging.h | 4 ++++
src/util/virterror.c | 22 ++++++++++++++++++++--
5 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 66f1388..0b75624 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -3083,6 +3083,8 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
+ virLogSetDaemonMode(true);
+
while (1) {
int optidx = 0;
int c;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0547cdf..a148620 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -485,6 +485,7 @@ virRegisterStorageDriver;
# logging.h
virLogDefineFilter;
virLogDefineOutput;
+virLogGetDaemonMode;
virLogGetDefaultPriority;
virLogGetFilters;
virLogGetNbFilters;
@@ -496,6 +497,7 @@ virLogParseDefaultPriority;
virLogParseFilters;
virLogParseOutputs;
virLogReset;
+virLogSetDaemonMode;
virLogSetDefaultPriority;
virLogSetFromEnv;
virLogShutdown;
diff --git a/src/util/logging.c b/src/util/logging.c
index d65dec0..e87ed6a 100644
--- a/src/util/logging.c
+++ b/src/util/logging.c
@@ -170,6 +170,7 @@ static const char *virLogPriorityString(virLogPriority lvl) {
}
static int virLogInitialized = 0;
+static bool virLogDaemonMode = false;
/**
* virLogStartup:
@@ -589,6 +590,19 @@ void virLogMessage(const char *category, int priority, const char *funcname,
VIR_FREE(msg);
}
+bool
+virLogGetDaemonMode(void)
+{
+ return virLogDaemonMode;
+}
+
+void
+virLogSetDaemonMode(bool daemonMode)
+{
+ virLogDaemonMode = daemonMode;
+}
+
+
static int virLogOutputToFd(const char *category ATTRIBUTE_UNUSED,
int priority ATTRIBUTE_UNUSED,
const char *funcname ATTRIBUTE_UNUSED,
diff --git a/src/util/logging.h b/src/util/logging.h
index 574f68d..ef78e97 100644
--- a/src/util/logging.h
+++ b/src/util/logging.h
@@ -22,6 +22,8 @@
#ifndef __VIRTLOG_H_
# define __VIRTLOG_H_
+# include <stdbool.h>
+
# include "internal.h"
# include "buf.h"
@@ -139,5 +141,7 @@ extern int virLogParseOutputs(const char *output);
extern void virLogMessage(const char *category, int priority,
const char *funcname, long long linenr, int flags,
const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(6, 7);
+extern bool virLogGetDaemonMode(void);
+extern void virLogSetDaemonMode(bool daemonMode);
#endif
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 83c4c9d..14d92fd 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -64,6 +64,18 @@ void *virUserData = NULL; /* associated data */
}} \
}
+static virLogPriority virErrorLevelPriority(virErrorLevel level) {
+ switch (level) {
+ case VIR_ERR_NONE:
+ return(VIR_LOG_INFO);
+ case VIR_ERR_WARNING:
+ return(VIR_LOG_WARN);
+ case VIR_ERR_ERROR:
+ return(VIR_LOG_ERROR);
+ }
+ return(VIR_LOG_ERROR);
+}
+
static const char *virErrorDomainName(virErrorDomain domain) {
const char *dom = "unknown";
switch (domain) {
@@ -703,9 +715,15 @@ virRaiseErrorFull(virConnectPtr conn ATTRIBUTE_UNUSED,
/*
* Hook up the error or warning to the logging facility
* XXXX should we include filename as 'category' instead of domain name ?
+ *
+ * When inside libvirtd don't log errors, this would pollute the syslog
+ * with client errors. Those will get reported and logged on the client
+ * side anyway.
*/
- virLogMessage(virErrorDomainName(domain), VIR_LOG_INFO,
- funcname, linenr, 1, "%s", str);
+ if (!virLogGetDaemonMode()) {
+ virLogMessage(virErrorDomainName(domain), virErrorLevelPriority(level),
+ funcname, linenr, 1, "%s", str);
+ }
/*
* Save the information about the error
--
1.7.0.4
14 years
[libvirt] [PATCH] remote: Fix TLS transport on Windows
by Matthias Bolte
gnulib wraps Windows' SOCKET handle based send() and recv() functions
into file descriptor based ones that are use in libvirt. By default
GnuTLS uses the SOCKET handle based send() and recv() on Windows. This
makes gnutls_handshake() fail internally with a WSAENOTSOCK error because
libvirt passes a file descriptor; GnuTLS needs the SOCKET handle.
To avoid this mismatch make sure that GnuTLS uses gnulib's replacment
functions, by setting custom pull() and push() functions for GnuTLS.
---
src/remote/remote_driver.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index f45476a..87977ab 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1212,6 +1212,20 @@ initialize_gnutls(void)
static int verify_certificate (virConnectPtr conn, struct private_data *priv, gnutls_session_t session);
+#if HAVE_WINSOCK2_H
+static ssize_t
+custom_gnutls_push(void *s, const void *buf, size_t len)
+{
+ return send((int)(long)s, buf, len, 0);
+}
+
+static ssize_t
+custom_gnutls_pull(void *s, void *buf, size_t len)
+{
+ return recv((int)(long)s, buf, len, 0);
+}
+#endif
+
static gnutls_session_t
negotiate_gnutls_on_connection (virConnectPtr conn,
struct private_data *priv,
@@ -1266,6 +1280,13 @@ negotiate_gnutls_on_connection (virConnectPtr conn,
gnutls_transport_set_ptr (session,
(gnutls_transport_ptr_t) (long) priv->sock);
+#if HAVE_WINSOCK2_H
+ /* Make sure GnuTLS uses gnulib's replacment functions for send() and
+ * recv() on Windows */
+ gnutls_transport_set_push_function(session, custom_gnutls_push);
+ gnutls_transport_set_pull_function(session, custom_gnutls_pull);
+#endif
+
/* Perform the TLS handshake. */
again:
err = gnutls_handshake (session);
--
1.7.0.4
14 years