On Fri, Dec 17, 2010 at 04:49:27PM +0800, Wen Congyang wrote:
implement auto cold migration fallback at timeout
Signed-off-by: Wen Congyang <wency(a)cn.fujitsu.com>
---
tools/virsh.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index cbde085..b95c8fe 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -3379,9 +3379,32 @@ static const vshCmdOptDef opts_migrate[] = {
{"desturi", VSH_OT_DATA, VSH_OFLAG_REQ, N_("connection URI of the
destination host")},
{"migrateuri", VSH_OT_DATA, 0, N_("migration URI, usually can be
omitted")},
{"dname", VSH_OT_DATA, 0, N_("rename to new name during migration (if
supported)")},
+ {"timeout", VSH_OT_INT, 0, N_("auto cold migration fallback when live
migration timeouts(in seconds)")},
{NULL, 0, 0, NULL}
};
+static void migrateTimeoutHandler(void *data)
+{
+ virDomainPtr dom = (virDomainPtr)data;
+ virDomainInfo info;
+ unsigned int id;
+
+ id = virDomainGetID(dom);
+ if (id == ((unsigned int)-1))
+ return;
+
+ /* The error reason has been reported in virDomainGetInfo() and
+ * virDomainSuspend() when it fails. So we do not check the return value.
+ */
+ if (virDomainGetInfo(dom, &info) == 0) {
+ if (info.state == VIR_DOMAIN_SHUTOFF)
+ return;
+
+ /* suspend the domain when migration timeouts. */
+ virDomainSuspend(dom);
+ }
+}
+
static int
cmdMigrate (vshControl *ctl, const vshCmd *cmd)
{
@@ -3389,6 +3412,8 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
const char *desturi;
const char *migrateuri;
const char *dname;
+ long long timeout;
+ virTimerPtr migratetimer = NULL;
int flags = 0, found, ret = FALSE;
if (!vshConnectionUsability (ctl, ctl->conn))
@@ -3426,6 +3451,28 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptBool (cmd, "copy-storage-inc"))
flags |= VIR_MIGRATE_NON_SHARED_INC;
+ timeout = vshCommandOptLongLong(cmd, "timeout", &found);
+ if (found) {
+ if (! flags & VIR_MIGRATE_LIVE) {
+ vshError(ctl, "%s", _("migrate: Unexpected timeout for cold
migration"));
+ goto done;
+ }
+
+ if (timeout < 1) {
+ vshError(ctl, "%s", _("migrate: Invalid timeout"));
+ goto done;
+ }
+
+ migratetimer = virNewTimer(migrateTimeoutHandler, (void *)dom);
+ if (!migratetimer)
+ goto done;
+
+ if (virStartTimer() < 0) {
I thinks it's better to call this function at virsh initialization stage
and stop it when virsh ends, then at anytime in the lifetime of virsh
we can call virAddTimer/virDelTimer to add/delete a timer.
+ vshError(ctl, "%s", _("migrate: failed to
start timer"));
+ goto done;
+ }
+ }
+
if ((flags & VIR_MIGRATE_PEER2PEER) ||
vshCommandOptBool (cmd, "direct")) {
/* For peer2peer migration or direct migration we only expect one URI
@@ -3436,6 +3483,13 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
goto done;
}
+ if (migratetimer) {
+ if (virAddTimer(migratetimer, timeout * 1000) < 0) {
+ vshError(ctl, "%s", _("migrate: failed to add
timer"));
+ goto done;
+ }
+ }
+
if (virDomainMigrateToURI (dom, desturi, flags, dname, 0) == 0)
ret = TRUE;
} else {
@@ -3446,6 +3500,13 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
dconn = virConnectOpenAuth (desturi, virConnectAuthPtrDefault, 0);
if (!dconn) goto done;
+ if (migratetimer) {
+ if (virAddTimer(migratetimer, timeout * 1000) < 0) {
+ vshError(ctl, "%s", _("migrate: failed to add
timer"));
+ goto done;
+ }
+ }
+
ddom = virDomainMigrate (dom, dconn, flags, dname, migrateuri, 0);
if (ddom) {
virDomainFree(ddom);
@@ -3455,6 +3516,11 @@ cmdMigrate (vshControl *ctl, const vshCmd *cmd)
}
done:
+ if (migratetimer) {
+ virStopTimer();
See above.
+ virDelTimer(migratetimer);
+ virFreeTimer(migratetimer);
+ }
if (dom) virDomainFree (dom);
return ret;
}
--
1.7.1
--
Thanks,
Hu Tao