[libvirt] [PATCH 0/6 v2] New APIs to get/set node memory parameters
by Osier Yang
v1:
https://www.redhat.com/archives/libvir-list/2012-September/msg00517.html
v1 - v2:
* Rename virNode{Get,Set}SharedMemoryParameters to
virNode{Get,Set}MemoryParameters, in case of we could add more
node memory tunables in future.
As a result of RFC:
https://www.redhat.com/archives/libvir-list/2012-August/msg01998.html,
this adds two new APIs (virNode{Get,Set}MemoryParameters) to get
and set the host shared memory tunables (ksm under linux).
Osier Yang (6):
node_memory: Define the APIs to get/set shared memory parameters
node_memory: Wire up the RPC protocol
node_memory: Implement the internal APIs
node_memory: Support get/set memory parameters for drivers
node_memory: Expose the APIs to virsh
node_memory: Expose the APIs to Python bindings
daemon/remote.c | 59 +++++++
include/libvirt/libvirt.h.in | 63 ++++++++
python/generator.py | 2 +
python/libvirt-override-api.xml | 13 ++
python/libvirt-override.c | 125 +++++++++++++++
src/driver.h | 14 ++
src/libvirt.c | 121 ++++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 2 +
src/lxc/lxc_driver.c | 2 +
src/nodeinfo.c | 332 +++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 10 ++
src/qemu/qemu_driver.c | 2 +
src/remote/remote_driver.c | 50 ++++++
src/remote/remote_protocol.x | 24 +++-
src/remote_protocol-structs | 20 +++
src/rpc/gendispatch.pl | 3 +
src/uml/uml_driver.c | 2 +
src/xen/xen_driver.c | 3 +
tools/virsh-host.c | 116 ++++++++++++++
tools/virsh.pod | 8 +
21 files changed, 972 insertions(+), 1 deletions(-)
--
1.7.7.3
12 years, 2 months
[libvirt] [PATCH 1/2] Add support for EOI with APIC
by Martin Kletzander
New options is added to support EOI (End of Interrupt) exposure for
guests. As it makes sense only when APIC is enabled, I added this into
the <apic> element in <features> because this should be tri-state
option (cannot be handled as standalone feature).
---
docs/formatdomain.html.in | 7 +++++++
docs/schemas/domaincommon.rng | 9 ++++++++-
src/conf/domain_conf.c | 35 ++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 11 +++++++++++
src/libvirt_private.syms | 2 ++
5 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 503685f..66319d0 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1018,6 +1018,13 @@
<dd>ACPI is useful for power management, for example, with
KVM guests it is required for graceful shutdown to work.
</dd>
+ <dt><code>apic</code></dt>
+ <dd>APIC allows the use of programmable IRQ
+ management. <span class="since">Since 0.10.2 (QEMU only)</span>
+ there is an optional attribute <code>eoi</code> with values "on"
+ and "off" which toggle the availability of EOI (End of
+ Interrupt) for the guest.
+ </dd>
<dt><code>hap</code></dt>
<dd>Enable use of Hardware Assisted Paging if available in
the hardware.
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c2c6184..029c796 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2859,7 +2859,14 @@
</optional>
<optional>
<element name="apic">
- <empty/>
+ <optional>
+ <attribute name="eoi">
+ <choice>
+ <value>on</value>
+ <value>off</value>
+ </choice>
+ </attribute>
+ </optional>
</element>
</optional>
<optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 292cc9a..89c08da 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -110,6 +110,11 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"viridian",
"privnet")
+VIR_ENUM_IMPL(virDomainApicEoi, VIR_DOMAIN_APIC_EOI_LAST,
+ "default",
+ "on",
+ "off")
+
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
"destroy",
"restart",
@@ -8621,6 +8626,28 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto error;
}
def->features |= (1 << val);
+ if (val == VIR_DOMAIN_FEATURE_APIC) {
+ char *attrstr = NULL;
+ if (virAsprintf(&attrstr,
+ "string(./features/%s/@eoi)",
+ nodes[i]->name) < 0)
+ goto no_memory;
+
+ tmp = virXPathString(attrstr, ctxt);
+ if (tmp) {
+ int eoi;
+ if ((eoi = virDomainApicEoiTypeFromString(tmp)) < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown value for attribute eoi: %s"),
+ nodes[i]->name);
+ VIR_FREE(tmp);
+ goto error;
+ }
+ def->apic_eoi = eoi;
+ VIR_FREE(tmp);
+ }
+ VIR_FREE(attrstr);
+ }
}
VIR_FREE(nodes);
}
@@ -13413,7 +13440,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
_("unexpected feature %d"), i);
goto cleanup;
}
- virBufferAsprintf(buf, " <%s/>\n", name);
+ virBufferAsprintf(buf, " <%s", name);
+ if (i == VIR_DOMAIN_FEATURE_APIC && def->apic_eoi) {
+ virBufferAsprintf(buf,
+ " eoi='%s'",
+ virDomainApicEoiTypeToString(def->apic_eoi));
+ }
+ virBufferAsprintf(buf, "/>\n");
}
}
virBufferAddLit(buf, " </features>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3995c2d..86dae7d 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1351,6 +1351,14 @@ enum virDomainFeature {
VIR_DOMAIN_FEATURE_LAST
};
+enum virDomainApicEoi {
+ VIR_DOMAIN_APIC_EOI_DEFAULT = 0,
+ VIR_DOMAIN_APIC_EOI_ON,
+ VIR_DOMAIN_APIC_EOI_OFF,
+
+ VIR_DOMAIN_APIC_EOI_LAST,
+};
+
enum virDomainLifecycleAction {
VIR_DOMAIN_LIFECYCLE_DESTROY,
VIR_DOMAIN_LIFECYCLE_RESTART,
@@ -1642,6 +1650,8 @@ struct _virDomainDef {
virDomainOSDef os;
char *emulator;
int features;
+ /* enum virDomainApicEoi */
+ int apic_eoi;
virDomainClockDef clock;
@@ -2104,6 +2114,7 @@ VIR_ENUM_DECL(virDomainTaint)
VIR_ENUM_DECL(virDomainVirt)
VIR_ENUM_DECL(virDomainBoot)
VIR_ENUM_DECL(virDomainFeature)
+VIR_ENUM_DECL(virDomainApicEoi)
VIR_ENUM_DECL(virDomainLifecycle)
VIR_ENUM_DECL(virDomainLifecycleCrash)
VIR_ENUM_DECL(virDomainPMState)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0494e1f..5dd9313 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -263,6 +263,8 @@ virBlkioDeviceWeightArrayClear;
virDiskNameToBusDeviceIndex;
virDiskNameToIndex;
virDomainActualNetDefFree;
+virDomainApicEoiTypeFromString;
+virDomainApicEoiTypeToString;
virDomainAssignDef;
virDomainBlockedReasonTypeFromString;
virDomainBlockedReasonTypeToString;
--
1.7.12
12 years, 2 months
[libvirt] [PATCH v3 0/9] improve virBitmap
by Hu Tao
In many places we store bitmap info in a chunk of data
(pointed to by a char *), and have redundant codes to
set/unset bits. This series extends virBitmap, and convert
those codes to use virBitmap.
patch 01 is based on
https://www.redhat.com/archives/libvir-list/2012-September/msg00644.html
changes:
v3:
- renaming member variables of virBitmap
- rewrite virBitmapFormat using virBitmapNextSetBit
- store bits in machine native endian format
- more tests of virBitmap
v2:
- fix bug in qemuSetupCgroupForEmulator
- new function virBitmapNextSetBit
- virBitmapcmp -> virBitmapEqual
- virBitmap: store bits in little endian format
- some improvements of virBitmap
- fix some memory leaks
Hu Tao (9):
bitmap: add a new member variable map_len
New functions for virBitmap
use virBitmap to store cpupin info
use virBitmap to store cpu affinity info
use virBitmap to store numa nodemask info.
use virBitmap to store cpumask info.
use virBitmap to store cells' cpumask info.
use virBitmap to store nodeinfo.
remove virDomainCpuSetFormat and virDomainCpuSetParse
.gitignore | 1 +
src/conf/cpu_conf.c | 17 +-
src/conf/cpu_conf.h | 3 +-
src/conf/domain_conf.c | 392 ++++++----------------------------
src/conf/domain_conf.h | 18 +-
src/libvirt_private.syms | 14 +-
src/lxc/lxc_controller.c | 56 +++--
src/nodeinfo.c | 26 +--
src/nodeinfo.h | 6 +-
src/parallels/parallels_driver.c | 5 +-
src/qemu/qemu_cgroup.c | 10 +-
src/qemu/qemu_cgroup.h | 2 +-
src/qemu/qemu_command.c | 43 +---
src/qemu/qemu_driver.c | 168 +++++++--------
src/qemu/qemu_process.c | 141 ++++---------
src/test/test_driver.c | 5 +-
src/util/bitmap.c | 429 ++++++++++++++++++++++++++++++++++++--
src/util/bitmap.h | 34 +++
src/util/processinfo.c | 36 ++--
src/util/processinfo.h | 9 +-
src/vmx/vmx.c | 36 ++--
tests/Makefile.am | 7 +-
tests/cpuset | 2 +-
tests/virbitmaptest.c | 362 ++++++++++++++++++++++++++++++++
24 files changed, 1126 insertions(+), 696 deletions(-)
create mode 100644 tests/virbitmaptest.c
--
1.7.10.2
12 years, 2 months
[libvirt] [PATCH 0/7] New APIs to get/set node shared memory parameters
by Osier Yang
As a result of RFC:
https://www.redhat.com/archives/libvir-list/2012-August/msg01998.html,
this adds two new APIs (virNode{Get,Set}SharedMemoryParameters) to get
and set the host shared memory tunables (ksm under linux).
Osier Yang (7):
Improve virTypedParameterValidateSet
shared_memory: Define the APIs to get/set shared memory parameters
shared_memory: Wire up the RPC protocol
shared_memory: Implement the internal APIs
shared_memory: Support get/set shared memory parameters for drivers
shared_memory: Expose the APIs to virsh
shared_memory: Expose the APIs to Python bindings
daemon/remote.c | 61 +++++++
include/libvirt/libvirt.h.in | 63 +++++++
python/generator.py | 2 +
python/libvirt-override-api.xml | 13 ++
python/libvirt-override.c | 125 ++++++++++++++
src/driver.h | 14 ++
src/libvirt.c | 141 +++++++++++++++-
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 2 +
src/lxc/lxc_driver.c | 2 +
src/nodeinfo.c | 344 +++++++++++++++++++++++++++++++++++++++
src/nodeinfo.h | 10 +
src/qemu/qemu_driver.c | 2 +
src/remote/remote_driver.c | 50 ++++++
src/remote/remote_protocol.x | 24 +++-
src/remote_protocol-structs | 20 +++
src/rpc/gendispatch.pl | 3 +
src/uml/uml_driver.c | 2 +
src/xen/xen_driver.c | 3 +
tools/virsh-host.c | 110 +++++++++++++
tools/virsh.pod | 8 +
21 files changed, 990 insertions(+), 11 deletions(-)
--
1.7.7.3
12 years, 2 months
[libvirt] [PATCH] snapshot: fix rollback failure in transaction mode
by Guannan Ren
After failure of qemu transaction command, the snapshot file still
be there with non-zero in size. In order to unlink the file, the
patch removes the file size checking.
---
src/qemu/qemu_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 8e8e00c..1fedfb8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10833,7 +10833,7 @@ qemuDomainSnapshotUndoSingleDiskActive(struct qemud_driver *driver,
if (virDomainLockDiskDetach(driver->lockManager, vm, disk) < 0)
VIR_WARN("Unable to release lock on %s", disk->src);
if (need_unlink && stat(disk->src, &st) == 0 &&
- st.st_size == 0 && S_ISREG(st.st_mode) && unlink(disk->src) < 0)
+ S_ISREG(st.st_mode) && unlink(disk->src) < 0)
VIR_WARN("Unable to remove just-created %s", disk->src);
/* Update vm in place to match changes. */
--
1.7.11.2
12 years, 2 months
[libvirt] [PATCH 1/1 V2] Migrate per-port data for Open vSwitch ports during Qemu Live Migration
by Kyle Mestery
Add the ability to migrate per-port data on Open vSwitch
ports during qemu live migration. A controller can use this
to store data relating to each port, and have it migrated
with the virtual machine and populated on the destination
host.
Signed-off-by: Kyle Mestery <kmestery(a)cisco.com>
Cc: Laine Stump <laine(a)laine.org>
---
src/qemu/qemu_migration.c | 246 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 244 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1b21ef6..8c1a8f1 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -70,6 +70,7 @@ enum qemuMigrationCookieFlags {
QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS,
QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE,
QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT,
+ QEMU_MIGRATION_COOKIE_FLAG_OVS_PORT_DATA,
QEMU_MIGRATION_COOKIE_FLAG_LAST
};
@@ -77,12 +78,13 @@ enum qemuMigrationCookieFlags {
VIR_ENUM_DECL(qemuMigrationCookieFlag);
VIR_ENUM_IMPL(qemuMigrationCookieFlag,
QEMU_MIGRATION_COOKIE_FLAG_LAST,
- "graphics", "lockstate", "persistent");
+ "graphics", "lockstate", "persistent", "ovsportdata");
enum qemuMigrationCookieFeatures {
QEMU_MIGRATION_COOKIE_GRAPHICS = (1 << QEMU_MIGRATION_COOKIE_FLAG_GRAPHICS),
QEMU_MIGRATION_COOKIE_LOCKSTATE = (1 << QEMU_MIGRATION_COOKIE_FLAG_LOCKSTATE),
QEMU_MIGRATION_COOKIE_PERSISTENT = (1 << QEMU_MIGRATION_COOKIE_FLAG_PERSISTENT),
+ QEMU_MIGRATION_COOKIE_OVS_PORT_DATA = (1 << QEMU_MIGRATION_COOKIE_FLAG_OVS_PORT_DATA),
};
typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -95,6 +97,19 @@ struct _qemuMigrationCookieGraphics {
char *tlsSubject;
};
+typedef struct _qemuMigrationCookieOvsPortData qemuMigrationCookieOvsPortData;
+typedef qemuMigrationCookieOvsPortData *qemuMigrationCookieOvsPortDataPtr;
+struct _qemuMigrationCookieOvsPortData {
+ /* How many virtual NICs are we saving data for? */
+ int nnets;
+
+ /*
+ * Array of pointers to saved data. Each VIF will have it's own
+ * data to transfer.
+ */
+ char **portdata;
+};
+
typedef struct _qemuMigrationCookie qemuMigrationCookie;
typedef qemuMigrationCookie *qemuMigrationCookiePtr;
struct _qemuMigrationCookie {
@@ -120,6 +135,9 @@ struct _qemuMigrationCookie {
/* If (flags & QEMU_MIGRATION_COOKIE_PERSISTENT) */
virDomainDefPtr persistent;
+
+ /* If (flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) */
+ qemuMigrationCookieOvsPortDataPtr ovsportdata;
};
static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
@@ -132,6 +150,24 @@ static void qemuMigrationCookieGraphicsFree(qemuMigrationCookieGraphicsPtr grap)
}
+static void qemuMigrationCookieOvsPortDataFree(qemuMigrationCookieOvsPortDataPtr
+ ovsportdata)
+{
+ int i;
+
+ if (!ovsportdata)
+ return;
+
+ for (i = 0; i < ovsportdata->nnets; i++) {
+ VIR_FREE(ovsportdata->portdata[i]);
+ }
+
+ VIR_FREE(ovsportdata->portdata);
+
+ VIR_FREE(ovsportdata);
+}
+
+
static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
{
if (!mig)
@@ -140,6 +176,10 @@ static void qemuMigrationCookieFree(qemuMigrationCookiePtr mig)
if (mig->flags & QEMU_MIGRATION_COOKIE_GRAPHICS)
qemuMigrationCookieGraphicsFree(mig->graphics);
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) {
+ qemuMigrationCookieOvsPortDataFree(mig->ovsportdata);
+ }
+
VIR_FREE(mig->localHostname);
VIR_FREE(mig->remoteHostname);
VIR_FREE(mig->name);
@@ -256,6 +296,60 @@ error:
}
+static qemuMigrationCookieOvsPortDataPtr
+qemuMigrationCookieOvsPortDataAlloc(struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ qemuMigrationCookieOvsPortDataPtr mig;
+ int i;
+ virCommandPtr cmd = NULL;
+ virDomainNetDefPtr netptr;
+
+ if (VIR_ALLOC(mig) < 0)
+ goto no_memory;
+
+ mig->nnets = def->nnets;
+
+ if (VIR_ALLOC_N(mig->portdata, def->nnets) < 0)
+ goto no_memory;
+
+ for (i = 0; i < def->nnets; i++) {
+ virNetDevVPortProfilePtr vport = virDomainNetGetActualVirtPortProfile(def->nets[i]);
+ netptr = def->nets[i];
+
+ if (vport && vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH) {
+ if (VIR_ALLOC(mig->portdata[i]) < 0)
+ goto no_memory;
+
+ cmd = virCommandNewArgList(OVSVSCTL, "get", "Interface",
+ netptr->ifname, "external_ids:PortData",
+ NULL);
+
+ virCommandSetOutputBuffer(cmd, &mig->portdata[i]);
+
+ /* Run the command */
+ if (virCommandRun(cmd, NULL) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to run command to get OVS port data for "
+ "interface %s"), netptr->ifname);
+ goto error;
+ }
+
+ /* Wipeout the newline */
+ mig->portdata[i][strlen(mig->portdata[i]) - 1] = '\0';
+ }
+ }
+
+ return mig;
+
+no_memory:
+ virReportOOMError();
+error:
+ qemuMigrationCookieOvsPortDataFree(mig);
+ return NULL;
+}
+
+
static qemuMigrationCookiePtr
qemuMigrationCookieNew(virDomainObjPtr dom)
{
@@ -370,6 +464,27 @@ qemuMigrationCookieAddPersistent(qemuMigrationCookiePtr mig,
}
+static int
+qemuMigrationCookieAddOvsPortData(qemuMigrationCookiePtr mig,
+ struct qemud_driver *driver,
+ virDomainObjPtr dom)
+{
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Migration ovs port data data already present"));
+ return -1;
+ }
+
+ if (dom->def->nnets >= 1) {
+ if (!(mig->ovsportdata = qemuMigrationCookieOvsPortDataAlloc(
+ driver, dom->def)))
+ return -1;
+ mig->flags |= QEMU_MIGRATION_COOKIE_OVS_PORT_DATA;
+ }
+
+ return 0;
+}
+
static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
qemuMigrationCookieGraphicsPtr grap)
@@ -389,6 +504,25 @@ static void qemuMigrationCookieGraphicsXMLFormat(virBufferPtr buf,
}
+static void qemuMigrationCookieOvsPortDataXMLFormat(virBufferPtr buf,
+ qemuMigrationCookieOvsPortDataPtr optr)
+{
+ int i;
+
+ virBufferAsprintf(buf, " <ovsportdata nnets='%d'>\n", optr->nnets);
+ if (optr->nnets > 0)
+ virBufferAsprintf(buf, " <vifs>\n");
+ for (i = 0; i < optr->nnets; i++) {
+ virBufferAsprintf(buf, " <vif num='%d' portdata='%s'/>\n",
+ i, optr->portdata[i]);
+ }
+ if (optr->nnets > 0)
+ virBufferAsprintf(buf, " </vifs>\n");
+
+ virBufferAddLit(buf, " </ovsportdata>\n");
+}
+
+
static int
qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
virBufferPtr buf,
@@ -439,6 +573,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
virBufferAdjustIndent(buf, -2);
}
+ if ((mig->flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) &&
+ mig->ovsportdata)
+ qemuMigrationCookieOvsPortDataXMLFormat(buf, mig->ovsportdata);
+
virBufferAddLit(buf, "</qemu-migration>\n");
return 0;
}
@@ -516,6 +654,57 @@ error:
}
+static qemuMigrationCookieOvsPortDataPtr
+qemuMigrationCookieOvsPortDataXMLParse(xmlXPathContextPtr ctxt)
+{
+ qemuMigrationCookieOvsPortDataPtr optr;
+ int i;
+ int n;
+ xmlNodePtr *vifs = NULL;
+
+ if (VIR_ALLOC(optr) < 0)
+ goto no_memory;
+
+ if (virXPathInt("string(./ovsportdata/@nnets)", ctxt, &optr->nnets) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing nnets attribute in migration data"));
+ goto error;
+ }
+
+ if (VIR_ALLOC_N(optr->portdata, optr->nnets) < 0)
+ goto no_memory;
+
+ if ((n = virXPathNodeSet("./ovsportdata/vifs/vif", ctxt, &vifs)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing vif information"));
+ goto error;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (VIR_ALLOC(optr->portdata[i]) < 0)
+ goto no_memory;
+
+ if (!(optr->portdata[i] = virXMLPropString(vifs[i], "portdata"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing portdata attribute in migration data"));
+ goto error;
+ }
+ }
+
+ VIR_FREE(vifs);
+
+ return optr;
+
+no_memory:
+ virReportOOMError();
+error:
+ if (vifs)
+ VIR_FREE(vifs);
+ qemuMigrationCookieOvsPortDataFree(optr);
+ return NULL;
+}
+
+
static int
qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
struct qemud_driver *driver,
@@ -662,6 +851,11 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
VIR_FREE(nodes);
}
+ if ((flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) &&
+ virXPathBoolean("count(./ovsportdata) > 0", ctxt) &&
+ (!(mig->ovsportdata = qemuMigrationCookieOvsPortDataXMLParse(ctxt))))
+ goto error;
+
return 0;
error:
@@ -721,6 +915,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
qemuMigrationCookieAddPersistent(mig, dom) < 0)
return -1;
+ if (flags & QEMU_MIGRATION_COOKIE_OVS_PORT_DATA &&
+ qemuMigrationCookieAddOvsPortData(mig, driver, dom) < 0)
+ return -1;
+
if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
return -1;
@@ -1050,6 +1248,44 @@ qemuDomainMigrateGraphicsRelocate(struct qemud_driver *driver,
}
+static int
+qemuDomainMigrateOPDRelocate(struct qemud_driver *driver ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ qemuMigrationCookiePtr cookie)
+{
+ virCommandPtr cmd = NULL;
+ virDomainNetDefPtr netptr;
+ int ret = 0;
+ int i;
+ virBufferPtr buf;
+
+ if (VIR_ALLOC(buf) < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < cookie->ovsportdata->nnets; i++) {
+ netptr = vm->def->nets[i];
+
+ virBufferAsprintf(buf, "external_ids:PortData=%s",
+ cookie->ovsportdata->portdata[i]);
+
+ cmd = virCommandNewArgList(OVSVSCTL, "set", "Interface",
+ netptr->ifname, virBufferCurrentContent(buf),
+ NULL);
+ /* Run the command */
+ if ((ret = virCommandRun(cmd, NULL)) < 0) {
+ virReportSystemError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to run command to set OVS port data for "
+ "interface %s"), vm->def->nets[i]->ifname);
+ }
+ }
+
+out:
+ return ret;
+}
+
+
/* This is called for outgoing non-p2p migrations when a connection to the
* client which initiated the migration was closed but we were waiting for it
* to follow up with the next phase, that is, in between
@@ -1994,7 +2230,8 @@ cleanup:
if (ret == 0 &&
qemuMigrationBakeCookie(mig, driver, vm, cookieout, cookieoutlen,
- QEMU_MIGRATION_COOKIE_PERSISTENT ) < 0)
+ QEMU_MIGRATION_COOKIE_PERSISTENT |
+ QEMU_MIGRATION_COOKIE_OVS_PORT_DATA) < 0)
VIR_WARN("Unable to encode migration cookie");
qemuMigrationCookieFree(mig);
@@ -2929,6 +3166,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
qemuDomainCleanupRemove(vm, qemuMigrationPrepareCleanup);
+ cookie_flags = QEMU_MIGRATION_COOKIE_OVS_PORT_DATA;
if (flags & VIR_MIGRATE_PERSIST_DEST)
cookie_flags |= QEMU_MIGRATION_COOKIE_PERSISTENT;
@@ -2956,6 +3194,10 @@ qemuMigrationFinish(struct qemud_driver *driver,
goto endjob;
}
+ if (mig->ovsportdata)
+ if (qemuDomainMigrateOPDRelocate(driver, vm, mig) < 0)
+ VIR_WARN("unable to provide data for OVS port data relocation");
+
if (flags & VIR_MIGRATE_PERSIST_DEST) {
virDomainDefPtr vmdef;
if (vm->persistent)
--
1.7.11.4
12 years, 2 months
[libvirt] [PATCH] qemu: wait for SPICE to migrate
by Michal Privoznik
Recently, there have been some improvements made to qemu so it
supports seamless migration or something very close to it.
However, it requires libvirt interaction. Once qemu is migrated,
the SPICE server needs to send its internal state to the destination.
Once it's done, it fires SPICE_MIGRATE_COMPLETED event and this
fact is advertised in 'query-spice' output as well.
We must not kill qemu until SPICE server finishes the transfer.
---
Okay, I am ignoring the event completely in this patch.
I am just asking for 'query-spice' until after 'query-migrate'
reports 'completed'. It's simple and small.
However, if there is a wider consensus I should catch the
event as well, e.g. so we don't have to enter the monitor
and thus have smaller overhead, I can rewrite this patch.
src/qemu/qemu_migration.c | 32 ++++++++++++++++++++++---
src/qemu/qemu_monitor.c | 22 +++++++++++++++++
src/qemu/qemu_monitor.h | 3 ++
src/qemu/qemu_monitor_json.c | 52 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 3 ++
5 files changed, 108 insertions(+), 4 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 99fc8ce..e4ec66d 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -891,11 +891,13 @@ static int
qemuMigrationUpdateJobStatus(struct qemud_driver *driver,
virDomainObjPtr vm,
const char *job,
- enum qemuDomainAsyncJob asyncJob)
+ enum qemuDomainAsyncJob asyncJob,
+ bool wait_for_spice)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int ret;
int status;
+ bool spice_migrated = true;
unsigned long long memProcessed;
unsigned long long memRemaining;
unsigned long long memTotal;
@@ -910,6 +912,13 @@ qemuMigrationUpdateJobStatus(struct qemud_driver *driver,
&memProcessed,
&memRemaining,
&memTotal);
+
+ /* If qemu says migrated, check spice */
+ if (wait_for_spice && (ret == 0) &&
+ (status == QEMU_MONITOR_MIGRATION_STATUS_COMPLETED))
+ ret = qemuMonitorGetSpiceMigrationStatus(priv->mon,
+ &spice_migrated);
+
qemuDomainObjExitMonitorWithDriver(driver, vm);
if (ret < 0 || virTimeMillisNow(&priv->job.info.timeElapsed) < 0) {
@@ -939,7 +948,8 @@ qemuMigrationUpdateJobStatus(struct qemud_driver *driver,
break;
case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED:
- priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
+ if (spice_migrated)
+ priv->job.info.type = VIR_DOMAIN_JOB_COMPLETED;
ret = 0;
break;
@@ -967,6 +977,12 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm,
{
qemuDomainObjPrivatePtr priv = vm->privateData;
const char *job;
+ bool wait_for_spice;
+
+ /* If guest uses SPICE we have to hold up migration finish
+ * until SPICE server transfers its data */
+ wait_for_spice = (vm->def->ngraphics == 1) &&
+ (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE);
switch (priv->job.asyncJob) {
case QEMU_ASYNC_JOB_MIGRATION_OUT:
@@ -988,7 +1004,8 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm,
/* Poll every 50ms for progress & to allow cancellation */
struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull };
- if (qemuMigrationUpdateJobStatus(driver, vm, job, asyncJob) < 0)
+ if (qemuMigrationUpdateJobStatus(driver, vm, job,
+ asyncJob, wait_for_spice) < 0)
goto cleanup;
if (dconn && virConnectIsAlive(dconn) <= 0) {
@@ -1840,6 +1857,7 @@ qemuMigrationRun(struct qemud_driver *driver,
int fd = -1;
unsigned long migrate_speed = resource ? resource : priv->migMaxBandwidth;
virErrorPtr orig_err = NULL;
+ bool wait_for_spice;
VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, "
"cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, "
@@ -1848,6 +1866,11 @@ qemuMigrationRun(struct qemud_driver *driver,
cookieout, cookieoutlen, flags, resource,
spec, spec->destType, spec->fwdType);
+ /* If guest uses SPICE we have to hold up migration finish
+ * until SPICE server transfers its data */
+ wait_for_spice = (vm->def->ngraphics == 1) &&
+ (vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE);
+
if (virLockManagerPluginUsesState(driver->lockManager) &&
!cookieout) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -1946,7 +1969,8 @@ qemuMigrationRun(struct qemud_driver *driver,
* connection from qemu which may never be initiated.
*/
if (qemuMigrationUpdateJobStatus(driver, vm, _("migration job"),
- QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
+ QEMU_ASYNC_JOB_MIGRATION_OUT,
+ wait_for_spice) < 0)
goto cancel;
while ((fd = accept(spec->dest.unix_socket.sock, NULL, NULL)) < 0) {
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index b43b15e..20bb333 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1844,6 +1844,28 @@ int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
return ret;
}
+int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
+ bool *spice_migrated)
+{
+ int ret;
+ VIR_DEBUG("mon=%p", mon);
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (mon->json) {
+ ret = qemuMonitorJSONGetSpiceMigrationStatus(mon, spice_migrated);
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("JSON monitor is required"));
+ return -1;
+ }
+
+ return ret;
+}
int qemuMonitorMigrateToFd(qemuMonitorPtr mon,
unsigned int flags,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index f206d49..d3a0877 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -346,6 +346,9 @@ int qemuMonitorGetMigrationStatus(qemuMonitorPtr mon,
unsigned long long *remaining,
unsigned long long *total);
+int qemuMonitorGetSpiceMigrationStatus(qemuMonitorPtr mon,
+ bool *spice_migrated);
+
typedef enum {
QEMU_MONITOR_MIGRATE_BACKGROUND = 1 << 0,
QEMU_MONITOR_MIGRATE_NON_SHARED_DISK = 1 << 1, /* migration with non-shared storage with full disk copy */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 8842817..63dbd25 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2487,6 +2487,58 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
}
+static int
+qemuMonitorJSONSpiceGetMigrationStatusReply(virJSONValuePtr reply,
+ bool *spice_migrated)
+{
+ virJSONValuePtr ret;
+ const char *migrated_str;
+
+ if (!(ret = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-spice reply was missing return data"));
+ return -1;
+ }
+
+ if (!(migrated_str = virJSONValueObjectGetString(ret, "migrated"))) {
+ /* Deliberately don't report error here as we are
+ * probably dealing with older qemu which doesn't
+ * report this yet. Pretend spice is migrated. */
+ *spice_migrated = true;
+ } else {
+ *spice_migrated = STREQ(migrated_str, "true");
+ }
+
+ return 0;
+}
+
+
+int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon,
+ bool *spice_migrated)
+{
+ int ret;
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-spice",
+ NULL);
+ virJSONValuePtr reply = NULL;
+
+ if (!cmd)
+ return -1;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONSpiceGetMigrationStatusReply(reply,
+ spice_migrated);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
+
+
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
unsigned int flags,
const char *uri)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index f5d515f..88edb73 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -132,6 +132,9 @@ int qemuMonitorJSONGetMigrationStatus(qemuMonitorPtr mon,
unsigned long long *remaining,
unsigned long long *total);
+int qemuMonitorJSONGetSpiceMigrationStatus(qemuMonitorPtr mon,
+ bool *spice_migrated);
+
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
unsigned int flags,
const char *uri);
--
1.7.8.6
12 years, 2 months
[libvirt] [PATCH] conf: avoid libvirt crash with empty address guestfwd channel
by Alex Jia
The 'def->target.addr' hasn't been initialized in virDomainChrDefNew() and
its value is always '0xffffffff', in addition, the following test scenario
hasn't also include 'port' element in channel XML block, so the branch
'if (addrStr == NULL)' is hit in virDomainChrDefParseTargetXML(), the
programming jumps to 'error' label to release relevant resources, and the
statement 'if (VIR_ALLOC(def->target.addr) < 0)' hasn't been executed then
the virDomainChrDefFree() will free 'def->target.addr'(0xffffffff) via
VIR_FREE(), which results in libvirt crash, to use valgrind can also
find a 'Invalid free() / delete / delete[]' error. This patch just adjusts
codes order to initialize 'def->target.addr' firstly.
With this patch, libvirt hasn't crash and can get a expected error message "
XML error: guestfwd channel does not define a target address".
How to reproduce?
1. define a guest with the following channel XML configuration
$ cat foo.xml
<snip>
<channel type='pty'>
<target type='guestfwd'/>
</channel>
</snip>
$ virsh define foo.xml
2. actual result
error: Failed to define domain from /tmp/foo.xml
error: End of file while reading data: Input/output error
error: Failed to reconnect to the hypervisor
GDB debugger information:
<snip>
Breakpoint 1, virDomainChrDefFree (def=0x7f8ab000ec70) at conf/domain_conf.c:1264
...ignore
1264 {
(gdb) p def->target
$2 = {port = -1, addr = 0xffffffff, name = 0xffffffff <Address 0xffffffff out of bounds>}
</snip>
RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=856489
Signed-off-by: Alex Jia <ajia(a)redhat.com>
---
src/conf/domain_conf.c | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2f8e5d2..02048c7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5231,6 +5231,11 @@ virDomainChrDefParseTargetXML(virCapsPtr caps,
addrStr = virXMLPropString(cur, "address");
portStr = virXMLPropString(cur, "port");
+ if (VIR_ALLOC(def->target.addr) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+
if (addrStr == NULL) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("guestfwd channel does not "
@@ -5238,11 +5243,6 @@ virDomainChrDefParseTargetXML(virCapsPtr caps,
goto error;
}
- if (VIR_ALLOC(def->target.addr) < 0) {
- virReportOOMError();
- goto error;
- }
-
if (virSocketAddrParse(def->target.addr, addrStr, AF_UNSPEC) < 0)
goto error;
--
1.7.1
12 years, 2 months
[libvirt] [PATCH] Use 'qemu-system-i386' as binary instead of 'qemu'.
by Richard W.M. Jones
I have added the attached patch to Fedora because Fedora (only?)
renames 'qemu' to 'qemu-system-i386'. As a result of this, on 32 bit
Fedora would run 'qemu-system-x86_64 [...] -cpu qemu32'.
In fact this caused no issues (I originally added the patch because
I suspected this was a cause of RHBZ#857026, but that doesn't
appear to be the case). But if we're going to package qemu-system-i386
we might as well run it. The alternative would be to delete that
binary altogether if it does nothing useful ...
Rich.
--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
12 years, 2 months
[libvirt] [PATCH 0/4 v2] Support to set disk wwn
by Osier Yang
v1 - v2:
* Validate wwn while parsing
* Error out earlier "if (disk->device == "lun" && disk->wwn)", no
logic change.
This introduces new element <wwn> for disk, to allow to set wwn
(just like setting serial number) for the virtual disk (Only QEMU
devices like ide-drive, ide-hd, ide-cd, scsi-disk, scsi-hd, and
scsi-cd support it).
Osier Yang (4):
schema: Add schema for disk <wwn>
conf: Parse and format disk <wwn>
qemu: Add caps to indentify if setting wwn is supported by qemu
qemu: Use disk wwn in qemu command line
docs/formatdomain.html.in | 6 +++
docs/schemas/basictypes.rng | 6 +++
docs/schemas/domaincommon.rng | 5 +++
docs/schemas/nodedev.rng | 6 ---
src/conf/domain_conf.c | 12 +++++++
src/conf/domain_conf.h | 1 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_capabilities.c | 4 ++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 34 +++++++++++++++++++
src/util/util.c | 17 +++++++++
src/util/util.h | 2 +
.../qemuxml2argv-disk-ide-wwn.args | 6 +++
.../qemuxml2argvdata/qemuxml2argv-disk-ide-wwn.xml | 28 ++++++++++++++++
.../qemuxml2argv-disk-scsi-disk-wwn.args | 10 ++++++
.../qemuxml2argv-disk-scsi-disk-wwn.xml | 35 ++++++++++++++++++++
tests/qemuxml2argvtest.c | 7 ++++
17 files changed, 176 insertions(+), 6 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-ide-wwn.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-ide-wwn.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-wwn.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-scsi-disk-wwn.xml
--
1.7.7.3
12 years, 2 months