[libvirt] [libvirt-glib][PATCH v2 1/2] gobject: Introduce gvir_connection_get_hypervisor_name
by Michal Privoznik
which is basically a wrapper for virConnectGetType().
---
examples/conn-test.c | 12 +++++++
libvirt-gobject/libvirt-gobject-connection.c | 44 ++++++++++++++++++++++++++
libvirt-gobject/libvirt-gobject-connection.h | 3 ++
libvirt-gobject/libvirt-gobject.sym | 5 +++
4 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/examples/conn-test.c b/examples/conn-test.c
index 8c70997..b90d2b0 100644
--- a/examples/conn-test.c
+++ b/examples/conn-test.c
@@ -31,11 +31,23 @@ do_connection_open(GObject *source,
{
GVirConnection *conn = GVIR_CONNECTION(source);
GError *err = NULL;
+ gchar *hv_name = NULL;
if (!gvir_connection_open_finish(conn, res, &err)) {
g_error("%s", err->message);
+ goto cleanup;
}
g_print("Connected to libvirt\n");
+
+ if (!(hv_name = gvir_connection_get_hypervisor_name(conn, &err))) {
+ g_error("%s", err->message);
+ goto cleanup;
+ }
+
+ g_print("Hypervisor name: %s\n", hv_name);
+
+cleanup:
+ g_free(hv_name);
g_object_unref(conn);
}
diff --git a/libvirt-gobject/libvirt-gobject-connection.c b/libvirt-gobject/libvirt-gobject-connection.c
index d826905..f317861 100644
--- a/libvirt-gobject/libvirt-gobject-connection.c
+++ b/libvirt-gobject/libvirt-gobject-connection.c
@@ -1025,6 +1025,50 @@ const gchar *gvir_connection_get_uri(GVirConnection *conn)
return conn->priv->uri;
}
+/**
+ * gvir_connection_get_hypervisor_name:
+ * @conn: a #GVirConnection
+ * @err: return location for any #GError
+ *
+ * Get name of current hypervisor used.
+ *
+ * Return value: new string that should be freed when no longer needed,
+ * or NULL upon error.
+ */
+gchar *
+gvir_connection_get_hypervisor_name(GVirConnection *conn,
+ GError **err)
+{
+ GVirConnectionPrivate *priv;
+ gchar *ret = NULL;
+ const char *type;
+
+ g_return_val_if_fail(GVIR_IS_CONNECTION(conn), NULL);
+
+ priv = conn->priv;
+ /* Stop another thread closing the connection just at the minute */
+ virConnectRef(priv->conn);
+ if (!priv->conn) {
+ g_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
+ "Connection is not open");
+ goto cleanup;
+ }
+
+ type = virConnectGetType(priv->conn);
+ if (!type) {
+ gvir_set_error_literal(err, GVIR_CONNECTION_ERROR, 0,
+ "Unable to get hypervisor name");
+ goto cleanup;
+ }
+
+ ret = g_strdup(type);
+
+cleanup:
+ if (priv->conn)
+ virConnectClose(priv->conn);
+ return ret;
+}
+
static void gvir_domain_ref(gpointer obj, gpointer ignore G_GNUC_UNUSED)
{
g_object_ref(obj);
diff --git a/libvirt-gobject/libvirt-gobject-connection.h b/libvirt-gobject/libvirt-gobject-connection.h
index d658b01..62eb024 100644
--- a/libvirt-gobject/libvirt-gobject-connection.h
+++ b/libvirt-gobject/libvirt-gobject-connection.h
@@ -112,6 +112,9 @@ gboolean gvir_connection_fetch_domains_finish(GVirConnection *conn,
const gchar *gvir_connection_get_uri(GVirConnection *conn);
+gchar *gvir_connection_get_hypervisor_name(GVirConnection *conn,
+ GError **err);
+
GList *gvir_connection_get_domains(GVirConnection *conn);
GVirDomain *gvir_connection_get_domain(GVirConnection *conn,
diff --git a/libvirt-gobject/libvirt-gobject.sym b/libvirt-gobject/libvirt-gobject.sym
index 67e5a4f..2c2f1f4 100644
--- a/libvirt-gobject/libvirt-gobject.sym
+++ b/libvirt-gobject/libvirt-gobject.sym
@@ -194,4 +194,9 @@ LIBVIRT_GOBJECT_0.1.2 {
gvir_domain_resume_finish;
} LIBVIRT_GOBJECT_0.1.1;
+LIBVIRT_GOBJECT_0.1.3 {
+ global:
+ gvir_connection_get_hypervisor_name;
+} LIBVIRT_GOBJECT_0.1.2;
+
# .... define new API here using predicted next version number ....
--
1.7.8.6
12 years, 3 months
[libvirt] A question about radvd
by Gene Czarcinski
Just curious but ...
I have on virtual network defined with one IPv6 definition on the
virtual interface. When that network is started, two radvd processes
are started with exactly the same command lines. When that network is
destroyed, the two radvd processes disappear.
Why two ? especially if identical.
Gene
12 years, 3 months
[libvirt] Can't successfully start libvirtd service
by Alex Jia
Hi all,
I compiled and installed libvirt from upstream, but I can't successfully
start libvirtd service recently, for details, please see the following steps:
# ./bootstrap && ./configure --prefix=/usr && make && make install
Notes, everything is okay.
# service libvirtd restart
Stopping libvirtd daemon: [FAILED]
Starting libvirtd daemon: libvirtd: /usr/lib64/libvirt.so.0: version `LIBVIRT_0.10.2' not found (required by libvirtd)
[FAILED]
# ll /usr/lib64/libvirt.so.0
lrwxrwxrwx. 1 root root 17 Sep 3 19:26 /usr/lib64/libvirt.so.0 -> libvirt.so.0.10.1
# ll src/.libs/libvirt.so.0
lrwxrwxrwx. 1 root root 17 Sep 12 17:58 src/.libs/libvirt.so.0 -> libvirt.so.0.10.1
Notes, I can't find a libvirt.so.0.10.2 under the /usr/lib64/ or src/.libs/.
Is 'LIBVIRT_0.10.2' a error version? thanks.
--
Regards,
Alex
12 years, 3 months
[libvirt] [libvirt-designer][PATCH v2 0/4] Basic disk & interface support
by Michal Privoznik
with small example called virtxml.
The first patch has been ACKed. I am sending it for completeness sake.
diff to v1:
-Martin's and Chritophe's review notes worked in.
Michal Privoznik (4):
Load osinfo DB on init
domain: Introduce disk support
examples: Create an example of usage program
domain: Introduce interface support
.gitignore | 1 +
Makefile.am | 2 +-
configure.ac | 12 +-
examples/Makefile.am | 21 ++
examples/virtxml.c | 395 ++++++++++++++++++++++++++
libvirt-designer/Makefile.am | 1 +
libvirt-designer/libvirt-designer-domain.c | 347 ++++++++++++++++++++++-
libvirt-designer/libvirt-designer-domain.h | 12 +-
libvirt-designer/libvirt-designer-internal.h | 30 ++
libvirt-designer/libvirt-designer-main.c | 17 +-
libvirt-designer/libvirt-designer.sym | 4 +
11 files changed, 837 insertions(+), 5 deletions(-)
create mode 100644 examples/Makefile.am
create mode 100644 examples/virtxml.c
create mode 100644 libvirt-designer/libvirt-designer-internal.h
--
1.7.8.6
12 years, 3 months
[libvirt] [PATCH 1/2] parallels: fix parallelsDoCmdRun in case of command failure
by Dmitry Guryanov
Don't try to dereferece NULL pointer.
---
src/parallels/parallels_utils.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/parallels/parallels_utils.c b/src/parallels/parallels_utils.c
index 35766b7..89a0d89 100644
--- a/src/parallels/parallels_utils.c
+++ b/src/parallels/parallels_utils.c
@@ -55,7 +55,7 @@ parallelsDoCmdRun(char **outbuf, const char *binary, va_list list)
cleanup:
VIR_FREE(scmd);
virCommandFree(cmd);
- if (ret)
+ if (ret && outbuf)
VIR_FREE(*outbuf);
return ret;
}
--
1.7.1
12 years, 3 months
[libvirt] [PATCH v2 1/1] Backcompt for console devices in virDomainDeviceInfoIterate
by Li Zhang
Histrically, the first <console> element is treated as the
alias of a <serial> device. In the virDomainDeviceInfoIterate,
This situation is not considered. It still handles the first <console>
element as another devices, which means that for console[0] with
serial targetType, it calls callback function another time.
It will cause the problem of address conflicts when assigning
spapr-vio address for serial device on pSeries guest.
For pSeries guest, the serial configuration in the xml file
is as the following:
<serial type='pty'>
<target port='0'/>
<address type='spapr-vio'/>
</serial>
Console configuration is default, the dumped xml file is as the following:
<serial type='pty'>
<source path='/dev/pts/5'/>
<target port='0'/>
<alias name='serial0'/>
<address type='spapr-vio' reg='0x30000000'/>
</serial>
<console type='pty' tty='/dev/pts/5'>
<source path='/dev/pts/5'/>
<target type='serial' port='0'/>
<alias name='serial0'/>
<address type='spapr-vio' reg='0x30000000'/>
</console>
It shows that the <console> device is the alias of serial device.
So its address is the same as the serial device. When dectecting
the conflicts in the qemuAssignSpaprVIOAddress the first console
and the serial device conflicts because virDomainDeviceInfoIterate()
still handle these as two different devices, and in the qemuAssignSpaprVIOAddress(),
it will compare these two devices' addressed. If they have same address,
it will report address confilict error.
So this patch is to handle the first console which targetType is serial
as the alias of serial device to avoid address conflicts error reported.
Signed-off-by: Li Zhang <zhlcindy(a)linux.vnet.ibm.com>
---
* v1 -> v2:
Rebase v1 on latest version of libvirt.
src/conf/domain_conf.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8952b69..0e71b06 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2054,6 +2054,9 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
return -1;
}
for (i = 0; i < def->nconsoles ; i++) {
+ if ((STREQ(def->os.type, "hvm")) && i == 0 &&
+ def->consoles[i]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
+ continue;
device.data.chr = def->consoles[i];
if (cb(def, &device, &def->consoles[i]->info, opaque) < 0)
return -1;
--
1.7.5.4
12 years, 3 months
[libvirt] [PATCH] build: avoid dirty docs on fresh bootstrap
by Eric Blake
* HACKING: Regenerate.
---
Pushing under the trivial rule.
HACKING | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/HACKING b/HACKING
index ab1a329..da5e771 100644
--- a/HACKING
+++ b/HACKING
@@ -36,11 +36,12 @@ Then, when you want to post your patches:
git send-email --cover-letter --no-chain-reply-to --annotate \
--to=libvir-list(a)redhat.com master
-(Note that the "git send-email" subcommand is usually not in the main git
-package, but part of a sub-package called "git-email".) For a single patch you
-can omit "--cover-letter", but series of a two or more patches needs a cover
-letter. If you get tired of typing "--to=libvir-list(a)redhat.com" designation
-you can set it in git config:
+(Note that the "git send-email" subcommand may not be in the main git package
+and using it may require installion of a separate package, for example the
+"git-email" package in Fedora.) For a single patch you can omit
+"--cover-letter", but a series of two or more patches needs a cover letter. If
+you get tired of typing "--to=libvir-list(a)redhat.com" designation you can set
+it in git config:
git config sendemail.to libvir-list(a)redhat.com
--
1.7.11.4
12 years, 3 months
[libvirt] [PATCH v7] support offline migration
by liguang
original migration did not aware of offline case
so, add code to support offline migration quietly
(did not disturb original migration) by pass
VIR_MIGRATE_OFFLINE flag to migration APIs if only
the domain is really inactive, and
migration process will not puzzled by domain
offline and exit unexpectedly.
these changes did not take care of disk images the
domain required, for them could be transferred by
other APIs as suggested, then VIR_MIGRATE_OFFLINE
should not combined with VIR_MIGRATE_NON_SHARED_*.
so, this migration result is just make domain
definition alive at target side.
Signed-off-by: liguang <lig.fnst(a)cn.fujitsu.com>
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 15 +++++++++++
src/qemu/qemu_migration.c | 54 ++++++++++++++++++++++++++++++++++++-----
src/qemu/qemu_migration.h | 3 +-
tools/virsh-domain.c | 6 ++++
5 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index cfe5047..77df2ab 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -995,6 +995,7 @@ typedef enum {
* whole migration process; this will be used automatically
* when supported */
VIR_MIGRATE_UNSAFE = (1 << 9), /* force migration even if it is considered unsafe */
+ VIR_MIGRATE_OFFLINE = (1 << 10), /* offline migrate */
} virDomainMigrateFlags;
/* Domain migration. */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b12d9bc..2380ccc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9641,6 +9641,15 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
}
if (!virDomainObjIsActive(vm)) {
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ if (flags & (VIR_MIGRATE_NON_SHARED_DISK|
+ VIR_MIGRATE_NON_SHARED_INC)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("migrating storage handled by volume APIs"));
+ goto endjob;
+ }
+ goto offline;
+ }
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -9653,6 +9662,7 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
if (qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0)
goto endjob;
+offline:
if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
cookieout, cookieoutlen,
flags)))
@@ -9888,6 +9898,11 @@ qemuDomainMigrateConfirm3(virDomainPtr domain,
goto cleanup;
}
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ ret = 0;
+ goto cleanup;
+ }
+
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
goto cleanup;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1b21ef6..4dd06c2 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_OFFLINE,
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", "offline");
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_OFFLINE = (1 << QEMU_MIGRATION_COOKIE_FLAG_OFFLINE),
};
typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -439,6 +441,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
virBufferAdjustIndent(buf, -2);
}
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ virBufferAsprintf(buf, " <offline/>\n");
+ }
+
virBufferAddLit(buf, "</qemu-migration>\n");
return 0;
}
@@ -662,6 +668,12 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
VIR_FREE(nodes);
}
+ if ((flags & QEMU_MIGRATION_COOKIE_OFFLINE)) {
+ if (virXPathBoolean("count(./offline) > 0", ctxt)) {
+ mig->flags |= QEMU_MIGRATION_COOKIE_OFFLINE;
+ }
+ }
+
return 0;
error:
@@ -721,6 +733,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
qemuMigrationCookieAddPersistent(mig, dom) < 0)
return -1;
+ if (flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ mig->flags |= QEMU_MIGRATION_COOKIE_OFFLINE;
+ }
+
if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
return -1;
@@ -1151,6 +1167,13 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
goto cleanup;
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ if (qemuMigrationBakeCookie(mig, driver, vm,
+ cookieout, cookieoutlen,
+ QEMU_MIGRATION_COOKIE_OFFLINE) < 0)
+ goto cleanup;
+ }
+
if (xmlin) {
if (!(def = virDomainDefParseString(driver->caps, xmlin,
QEMU_EXPECTED_VIRT_TYPES,
@@ -1314,6 +1337,15 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
goto endjob;
}
+ if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
+ QEMU_MIGRATION_COOKIE_OFFLINE)))
+ return ret;
+
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ ret = 0;
+ goto cleanup;
+ }
+
/* Start the QEMU daemon, with the same command-line arguments plus
* -incoming $migrateFrom
*/
@@ -1856,7 +1888,8 @@ qemuMigrationRun(struct qemud_driver *driver,
virLockManagerPluginGetName(driver->lockManager));
return -1;
}
-
+ if (flags & VIR_MIGRATE_OFFLINE)
+ return 0;
if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
QEMU_MIGRATION_COOKIE_GRAPHICS)))
goto cleanup;
@@ -2372,6 +2405,8 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver,
qemuDomainObjExitRemoteWithDriver(driver, vm);
}
VIR_FREE(dom_xml);
+ if (flags & VIR_MIGRATE_OFFLINE)
+ goto cleanup;
if (ret == -1)
goto cleanup;
@@ -2477,7 +2512,7 @@ finish:
vm->def->name);
cleanup:
- if (ddomain) {
+ if (ddomain || (flags & VIR_MIGRATE_OFFLINE)) {
virObjectUnref(ddomain);
ret = 0;
} else {
@@ -2554,7 +2589,7 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver,
}
/* domain may have been stopped while we were talking to remote daemon */
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
goto cleanup;
@@ -2617,7 +2652,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
goto cleanup;
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -2941,6 +2976,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
*/
if (retcode == 0) {
if (!virDomainObjIsActive(vm)) {
+ if (flags & VIR_MIGRATE_OFFLINE)
+ goto offline;
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
goto endjob;
@@ -3038,7 +3075,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
goto endjob;
}
}
-
+ offline:
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
event = virDomainEventNewFromObj(vm,
@@ -3120,7 +3157,10 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0)))
return -1;
-
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ rv = 0;
+ goto cleanup;
+ }
/* Did the migration go as planned? If yes, kill off the
* domain object, but if no, resume CPUs
*/
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 1740204..2bcaea0 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -36,7 +36,8 @@
VIR_MIGRATE_NON_SHARED_DISK | \
VIR_MIGRATE_NON_SHARED_INC | \
VIR_MIGRATE_CHANGE_PROTECTION | \
- VIR_MIGRATE_UNSAFE)
+ VIR_MIGRATE_UNSAFE | \
+ VIR_MIGRATE_OFFLINE)
enum qemuMigrationJobPhase {
QEMU_MIGRATION_PHASE_NONE = 0,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 4684466..ec25043 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6525,6 +6525,7 @@ static const vshCmdOptDef opts_migrate[] = {
{"dname", VSH_OT_DATA, 0, N_("rename to new name during migration (if supported)")},
{"timeout", VSH_OT_INT, 0, N_("force guest to suspend if live migration exceeds timeout (in seconds)")},
{"xml", VSH_OT_STRING, 0, N_("filename containing updated XML for the target")},
+ {"offline", VSH_OT_BOOL, 0, N_("for offline migration")},
{NULL, 0, 0, NULL}
};
@@ -6591,6 +6592,11 @@ doMigrate(void *opaque)
if (vshCommandOptBool(cmd, "unsafe"))
flags |= VIR_MIGRATE_UNSAFE;
+ if (vshCommandOptBool(cmd, "offline")) {
+ if (!virDomainIsActive(dom))
+ flags |= VIR_MIGRATE_OFFLINE;
+ }
+
if (xmlfile &&
virFileReadAll(xmlfile, 8192, &xml) < 0) {
vshError(ctl, _("file '%s' doesn't exist"), xmlfile);
--
1.7.2.5
12 years, 3 months
[libvirt] [PATCH] support offline migration
by liguang
original migration did not aware of offline case
so, add code to support offline migration quietly
(did not disturb original migration) by pass
VIR_MIGRATE_OFFLINE flag to migration APIs if only
the domain is really inactive, and
migration process will not puzzled by domain
offline and exit unexpectedly.
these changes did not take care of disk images the
domain required, for them could be transferred by
other APIs as suggested, then VIR_MIGRATE_OFFLINE
should not combined with VIR_MIGRATE_NON_SHARED_*.
so, this migration result is just make domain
definition alive at target side.
Signed-off-by: liguang <lig.fnst(a)cn.fujitsu.com>
---
include/libvirt/libvirt.h.in | 1 +
src/qemu/qemu_driver.c | 15 +++++++++++
src/qemu/qemu_migration.c | 54 ++++++++++++++++++++++++++++++++++++-----
src/qemu/qemu_migration.h | 3 +-
tools/virsh-domain.c | 6 ++++
5 files changed, 71 insertions(+), 8 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index cfe5047..77df2ab 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -995,6 +995,7 @@ typedef enum {
* whole migration process; this will be used automatically
* when supported */
VIR_MIGRATE_UNSAFE = (1 << 9), /* force migration even if it is considered unsafe */
+ VIR_MIGRATE_OFFLINE = (1 << 10), /* offline migrate */
} virDomainMigrateFlags;
/* Domain migration. */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b12d9bc..2380ccc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -9641,6 +9641,15 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
}
if (!virDomainObjIsActive(vm)) {
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ if (flags & (VIR_MIGRATE_NON_SHARED_DISK|
+ VIR_MIGRATE_NON_SHARED_INC)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("migrating storage handled by volume APIs"));
+ goto endjob;
+ }
+ goto offline;
+ }
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -9653,6 +9662,7 @@ qemuDomainMigrateBegin3(virDomainPtr domain,
if (qemuDomainCheckEjectableMedia(driver, vm, asyncJob) < 0)
goto endjob;
+offline:
if (!(xml = qemuMigrationBegin(driver, vm, xmlin, dname,
cookieout, cookieoutlen,
flags)))
@@ -9888,6 +9898,11 @@ qemuDomainMigrateConfirm3(virDomainPtr domain,
goto cleanup;
}
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ ret = 0;
+ goto cleanup;
+ }
+
if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT))
goto cleanup;
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 1b21ef6..4dd06c2 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_OFFLINE,
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", "offline");
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_OFFLINE = (1 << QEMU_MIGRATION_COOKIE_FLAG_OFFLINE),
};
typedef struct _qemuMigrationCookieGraphics qemuMigrationCookieGraphics;
@@ -439,6 +441,10 @@ qemuMigrationCookieXMLFormat(struct qemud_driver *driver,
virBufferAdjustIndent(buf, -2);
}
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ virBufferAsprintf(buf, " <offline/>\n");
+ }
+
virBufferAddLit(buf, "</qemu-migration>\n");
return 0;
}
@@ -662,6 +668,12 @@ qemuMigrationCookieXMLParse(qemuMigrationCookiePtr mig,
VIR_FREE(nodes);
}
+ if ((flags & QEMU_MIGRATION_COOKIE_OFFLINE)) {
+ if (virXPathBoolean("count(./offline) > 0", ctxt)) {
+ mig->flags |= QEMU_MIGRATION_COOKIE_OFFLINE;
+ }
+ }
+
return 0;
error:
@@ -721,6 +733,10 @@ qemuMigrationBakeCookie(qemuMigrationCookiePtr mig,
qemuMigrationCookieAddPersistent(mig, dom) < 0)
return -1;
+ if (flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ mig->flags |= QEMU_MIGRATION_COOKIE_OFFLINE;
+ }
+
if (!(*cookieout = qemuMigrationCookieXMLFormatStr(driver, mig)))
return -1;
@@ -1151,6 +1167,13 @@ char *qemuMigrationBegin(struct qemud_driver *driver,
QEMU_MIGRATION_COOKIE_LOCKSTATE) < 0)
goto cleanup;
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ if (qemuMigrationBakeCookie(mig, driver, vm,
+ cookieout, cookieoutlen,
+ QEMU_MIGRATION_COOKIE_OFFLINE) < 0)
+ goto cleanup;
+ }
+
if (xmlin) {
if (!(def = virDomainDefParseString(driver->caps, xmlin,
QEMU_EXPECTED_VIRT_TYPES,
@@ -1314,6 +1337,15 @@ qemuMigrationPrepareAny(struct qemud_driver *driver,
goto endjob;
}
+ if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
+ QEMU_MIGRATION_COOKIE_OFFLINE)))
+ return ret;
+
+ if (mig->flags & QEMU_MIGRATION_COOKIE_OFFLINE) {
+ ret = 0;
+ goto cleanup;
+ }
+
/* Start the QEMU daemon, with the same command-line arguments plus
* -incoming $migrateFrom
*/
@@ -1856,7 +1888,8 @@ qemuMigrationRun(struct qemud_driver *driver,
virLockManagerPluginGetName(driver->lockManager));
return -1;
}
-
+ if (flags & VIR_MIGRATE_OFFLINE)
+ return 0;
if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen,
QEMU_MIGRATION_COOKIE_GRAPHICS)))
goto cleanup;
@@ -2372,6 +2405,8 @@ static int doPeer2PeerMigrate3(struct qemud_driver *driver,
qemuDomainObjExitRemoteWithDriver(driver, vm);
}
VIR_FREE(dom_xml);
+ if (flags & VIR_MIGRATE_OFFLINE)
+ goto cleanup;
if (ret == -1)
goto cleanup;
@@ -2477,7 +2512,7 @@ finish:
vm->def->name);
cleanup:
- if (ddomain) {
+ if (ddomain || (flags & VIR_MIGRATE_OFFLINE)) {
virObjectUnref(ddomain);
ret = 0;
} else {
@@ -2554,7 +2589,7 @@ static int doPeer2PeerMigrate(struct qemud_driver *driver,
}
/* domain may have been stopped while we were talking to remote daemon */
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
goto cleanup;
@@ -2617,7 +2652,7 @@ qemuMigrationPerformJob(struct qemud_driver *driver,
if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0)
goto cleanup;
- if (!virDomainObjIsActive(vm)) {
+ if (!virDomainObjIsActive(vm) && !(flags & VIR_MIGRATE_OFFLINE)) {
virReportError(VIR_ERR_OPERATION_INVALID,
"%s", _("domain is not running"));
goto endjob;
@@ -2941,6 +2976,8 @@ qemuMigrationFinish(struct qemud_driver *driver,
*/
if (retcode == 0) {
if (!virDomainObjIsActive(vm)) {
+ if (flags & VIR_MIGRATE_OFFLINE)
+ goto offline;
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("guest unexpectedly quit"));
goto endjob;
@@ -3038,7 +3075,7 @@ qemuMigrationFinish(struct qemud_driver *driver,
goto endjob;
}
}
-
+ offline:
dom = virGetDomain (dconn, vm->def->name, vm->def->uuid);
event = virDomainEventNewFromObj(vm,
@@ -3120,7 +3157,10 @@ int qemuMigrationConfirm(struct qemud_driver *driver,
if (!(mig = qemuMigrationEatCookie(driver, vm, cookiein, cookieinlen, 0)))
return -1;
-
+ if (flags & VIR_MIGRATE_OFFLINE) {
+ rv = 0;
+ goto cleanup;
+ }
/* Did the migration go as planned? If yes, kill off the
* domain object, but if no, resume CPUs
*/
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index 1740204..2bcaea0 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -36,7 +36,8 @@
VIR_MIGRATE_NON_SHARED_DISK | \
VIR_MIGRATE_NON_SHARED_INC | \
VIR_MIGRATE_CHANGE_PROTECTION | \
- VIR_MIGRATE_UNSAFE)
+ VIR_MIGRATE_UNSAFE | \
+ VIR_MIGRATE_OFFLINE)
enum qemuMigrationJobPhase {
QEMU_MIGRATION_PHASE_NONE = 0,
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 4684466..ec25043 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -6525,6 +6525,7 @@ static const vshCmdOptDef opts_migrate[] = {
{"dname", VSH_OT_DATA, 0, N_("rename to new name during migration (if supported)")},
{"timeout", VSH_OT_INT, 0, N_("force guest to suspend if live migration exceeds timeout (in seconds)")},
{"xml", VSH_OT_STRING, 0, N_("filename containing updated XML for the target")},
+ {"offline", VSH_OT_BOOL, 0, N_("for offline migration")},
{NULL, 0, 0, NULL}
};
@@ -6591,6 +6592,11 @@ doMigrate(void *opaque)
if (vshCommandOptBool(cmd, "unsafe"))
flags |= VIR_MIGRATE_UNSAFE;
+ if (vshCommandOptBool(cmd, "offline")) {
+ if (!virDomainIsActive(dom))
+ flags |= VIR_MIGRATE_OFFLINE;
+ }
+
if (xmlfile &&
virFileReadAll(xmlfile, 8192, &xml) < 0) {
vshError(ctl, _("file '%s' doesn't exist"), xmlfile);
--
1.7.2.5
12 years, 3 months