[Kimchi-devel] [PATCH 2/2] Fixing Live Migration for the new-ui Guests tab
sguimaraes943 at gmail.com
sguimaraes943 at gmail.com
Wed Dec 2 16:09:21 UTC 2015
From: samhenri <samuel.guimaraes at eldorado.org.br>
Signed-off-by: samhenri <samuel.guimaraes at eldorado.org.br>
---
ui/js/src/kimchi.guest_livemigration.js | 113 +++++++++++++++++++++++++++++++
ui/js/src/kimchi.guest_main.js | 114 ++++++++++++++++++++------------
ui/pages/guest-migration.html.tmpl | 78 +++++++++++-----------
ui/pages/guests.html.tmpl | 4 +-
ui/pages/i18n.json.tmpl | 2 +
5 files changed, 229 insertions(+), 82 deletions(-)
create mode 100644 ui/js/src/kimchi.guest_livemigration.js
diff --git a/ui/js/src/kimchi.guest_livemigration.js b/ui/js/src/kimchi.guest_livemigration.js
new file mode 100644
index 0000000..04f092d
--- /dev/null
+++ b/ui/js/src/kimchi.guest_livemigration.js
@@ -0,0 +1,113 @@
+/*
+ * Project Kimchi
+ *
+ * Copyright IBM, Corp. 2013-2015
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+kimchi.guest_livemigration_main = function() {
+ kimchi.setupLiveMigrationFormEvent();
+ kimchi.initLiveMigrationDialog();
+};
+
+kimchi.startLiveMigration = function() {
+ var errorCallback = function() {
+ $("#migrateFormOk").prop("disabled", false);
+ $("#remoteHostName").removeAttr("readonly");
+ $("#username").removeAttr("readonly");
+ $("#password").removeAttr("readonly");
+ $("#deleteVM").removeAttr("readonly");
+ $("#deleteVM").prop("checked", false);
+ $("#migrateFormOk").text(i18n.KCHAPI6011M);
+ };
+ var values = kimchi.getLiveMigrationDialogValues();
+ var data = {
+ remote_host: values.remote_host,
+ user: values.user,
+ password: values.password
+ };
+ kimchi.migrateGuest(kimchi.selectedGuest, data, function() {
+ kimchi.listVmsAuto();
+ if ($("#deleteVM").prop("checked")) {
+ if (deleteQueue.indexOf(kimchi.selectedGuest) === -1) {
+ deleteQueue.push(kimchi.selectedGuest);
+ }
+ }
+ wok.window.close();
+ }, function(err) {
+ wok.message.error(err.responseJSON.reason, "#alert-modal-container");
+ errorCallback();
+ });
+};
+
+kimchi.initLiveMigrationDialog = function(okCallback) {
+ $("#migrateFormOk").on("click", function() {
+ $("#migrateFormOk").prop("disabled", true);
+ $("#remoteHostName").prop("readonly", "readonly");
+ $("#username").prop("readonly", "readonly");
+ $("#password").prop("readonly", "readonly");
+ $("#deleteVM").prop("readonly", "readonly");
+ $("#migrateFormOk").text(i18n.KCHAPI6010M);
+ kimchi.startLiveMigration();
+ });
+};
+
+
+kimchi.getLiveMigrationDialogValues = function() {
+ var data = {
+ remote_host: $("#remoteHostName").val(),
+ user: $("#username").val(),
+ password: $("#password").val()
+ };
+ return data;
+};
+
+kimchi.setupLiveMigrationFormEvent = function() {
+ $("#migrateFormOk").prop("disabled", true);
+ $("#remoteHostName").on("change keyup", function(event) {
+ if (!this.value) {
+ $(this).parent().addClass('has-error');
+ } else {
+ $(this).parent().removeClass('has-error');
+ }
+ kimchi.updateLiveMigrationButton();
+ });
+ $("#username").on("change keyup", function(event) {
+ if (this.value && !$("#password").val()) {
+ $("#username").parent().removeClass('has-warning');
+ $("#password").parent().addClass('has-warning');
+ } else {
+ $("#username").parent().removeClass('has-warning');
+ $("#password").parent().removeClass('has-warning');
+ }
+ kimchi.updateLiveMigrationButton();
+ });
+ $("#password").on("change keyup", function(event) {
+ if (this.value && !$("#username").val()) {
+ $("#username").parent().addClass('has-warning');
+ } else {
+ $("#username").parent().removeClass('has-warning');
+ $("#password").parent().removeClass('has-warning');
+ kimchi.updateLiveMigrationButton();
+ }
+ });
+};
+
+kimchi.updateLiveMigrationButton = function() {
+ if ($("input[type='text']").parent().hasClass("has-error") || $("input[type='text']").parent().hasClass("has-warning")) {
+ $("#migrateFormOk").prop("disabled", true);
+ } else {
+ $("#migrateFormOk").prop("disabled", false);
+ }
+};
diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
index 68e17cc..5b8993a 100644
--- a/ui/js/src/kimchi.guest_main.js
+++ b/ui/js/src/kimchi.guest_main.js
@@ -45,6 +45,8 @@ kimchi.sampleGuestObject = {
"access": "full"
};
+var deleteQueue = [];
+
kimchi.vmstart = function(event) {
var button = event.target;
if (!$(button).hasClass('loading')) {
@@ -229,6 +231,14 @@ kimchi.vmedit = function(event) {
});
};
+kimchi.vmmigrate = function(event) {
+ var button = event.target;
+ var vm = $(button).closest('li[name=guest]');
+ var vm_id = $(vm).attr("id");
+ kimchi.selectedGuest = vm_id;
+ wok.window.open('plugins/kimchi/guest-migration.html');
+};
+
kimchi.openVmConsole = function(event) {
var button = event.target;
var vm = $(button).closest('li[name=guest]');
@@ -303,22 +313,64 @@ kimchi.listVmsAuto = function() {
}, null, true);
return guests;
};
- var getMigratingGuests = function(){
- var guests = [];
- kimchi.getTasksByFilter('status=running&target_uri='+encodeURIComponent('^/vms/.+/migrate'), function(tasks) {
- for(var i=0;i<tasks.length;i++){
- var guestUri = tasks[i].target_uri;
- var guestName = guestUri.split('/')[4]
- guests.push($.extend({}, kimchi.sampleGuestObject, {name: guestName, isMigrating: true}));
- if(kimchi.trackingTasks.indexOf(tasks[i].id)==-1)
- kimchi.trackTask(tasks[i].id, null, function(err){
- wok.message.error(err.message);
- }, null);
+ var getMigratingGuests = function() {
+ var guests = [];
+ kimchi.getTasksByFilter('status=running&target_uri=' + encodeURIComponent('^/vms/.+/migrate'), function(tasks) {
+ for (var i = 0; i < tasks.length; i++) {
+ var guestUri = tasks[i].target_uri;
+ var guestName = guestUri.split('/')[4]
+ guests.push($.extend({}, kimchi.sampleGuestObject, {
+ name: guestName,
+ isMigrating: true
+ }));
+ if (kimchi.trackingTasks.indexOf(tasks[i].id) == -1)
+ kimchi.trackTask(tasks[i].id, null, function(err) {
+ wok.message.error(err.message);
+ }, null);
+ }
+ }, null, true);
+ return guests;
+ };
+ var getMigratedGuests = function() {
+ var guests = [];
+ kimchi.getTasksByFilter('status=finished&target_uri=' + encodeURIComponent('^/plugins/kimchi/vms/.+/migrate'), function(tasks) {
+ for (var i = 0; i < tasks.length; i++) {
+ var guestUri = tasks[i].target_uri;
+ var guestName = guestUri.split('/')[4]
+ guests.push(guestName);
+ if (kimchi.trackingTasks.indexOf(tasks[i].id) == -1)
+ kimchi.trackTask(tasks[i].id, null, function(err) {
+ wok.message.error(err.message);
+ }, null);
+ }
+ }, null, true);
+ return guests;
+ };
+ var deleteMigratedGuests = function() {
+ deleteQueue.reverse();
+ migratedGuests = getMigratedGuests();
+ migratedGuests.sort();
+ var i = deleteQueue.length;
+ while (i-- && i > 0) {
+ if (migratedGuests.indexOf(deleteQueue[i]) > -1) {
+ kimchi.deleteVM(deleteQueue[i], function(result) {
+ clearFromQueue(deleteQueue[i]);
+ }, function(err) {
+ wok.message.error(err.responseJSON.reason);
+ });
+ }
}
- }, null, true);
- return guests;
- };
+ };
+
+ var clearFromQueue = function(item) {
+ var toDequeue = deleteQueue.indexOf(item);
+ if (toDequeue != -1) {
+ deleteQueue.splice(toDequeue, 1);
+ };
+ };
+
kimchi.listVMs(function(result, textStatus, jqXHR) {
+ deleteMigratedGuests();
if (result && textStatus == "success") {
result = getMigratingGuests().concat(result);
result = getCloningGuests().concat(result);
@@ -359,27 +411,6 @@ kimchi.listVmsAuto = function() {
kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
var result = kimchi.guestElem.clone();
-
- var initializeMigratePanel = function() {
- $("#migrateFormOk").on("click", function() {
- //TODO: Get values from UI for remote_host, user, password
- var data = {
- "remote_host" : "ltc-hab1.aus.stglabs.ibm.com",
- "user" : "root",
- "password" : "passw0rd"
- };
- //TODO: Need to get guest to be passed in here
- kimchi.migrateGuest(guest, data, function(){
- kimchi.listVmsAuto();
- wok.window.close();
- }, function(err) {
- wok.message.error(err.responseJSON.reason);
- });
- });
- }
-
- initializeMigratePanel();
-
//Setup the VM list entry
var currentState = result.find('.guest-state');
var vmRunningBool = (vmObject.state == "running");
@@ -399,7 +430,6 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
//Add the OS Type and Icon
var osType = result.find('.distro-icon');
- console.log(vmObject);
if (vmObject.icon == 'plugins/kimchi/images/icon-fedora.png') {
osType.addClass('icon-fedora');
osType.attr('val', 'Fedora');
@@ -434,7 +464,7 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
//Setup the VM console thumbnail display
var curImg = vmObject.icon;
if (vmObject.screenshot) {
- curImg = vmObject.screenshot.replace(/^\//,'');
+ curImg = vmObject.screenshot.replace(/^\//, '');
}
var load_src = curImg || 'plugins/kimchi/images/icon-vm.png';
var tile_src = prevScreenImage || vmObject['load-src'];
@@ -625,7 +655,7 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
}
//Setup action event handlers
- if(!(vmObject.isCloning || vmObject.isCreating || vmObject.isMigrating)){
+ if (!(vmObject.isCloning || vmObject.isCreating || vmObject.isMigrating)) {
guestActions.find("[name=vm-start]").on("click", function(event) {
event.preventDefault();
@@ -684,9 +714,9 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
});
}, null);
});
- guestActions.find("[name=vm-migrate]").click(function(){
- var guest = $(this).closest('li[name=guest]').attr("id");
- wok.window.open('plugins/kimchi/guest-migration.html');
+ guestActions.find("[name=vm-migrate]").on('click', function() {
+ event.preventDefault();
+ kimchi.vmmigrate(event);
});
} else {
guestActions.find('.btn').attr('disabled', true);
@@ -694,7 +724,7 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
pendingText = result.find('.guest-pending .text')
if (vmObject.isCloning)
pendingText.text(i18n['KCHAPI6009M']);
- else if(vmObject.isMigrating)
+ else if (vmObject.isMigrating)
pendingText.text("Migrating");
else
pendingText.text(i18n['KCHAPI6008M']);
diff --git a/ui/pages/guest-migration.html.tmpl b/ui/pages/guest-migration.html.tmpl
index 278d22c..7cac2c5 100644
--- a/ui/pages/guest-migration.html.tmpl
+++ b/ui/pages/guest-migration.html.tmpl
@@ -21,45 +21,47 @@
#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True)
#silent _ = t.gettext
#silent _t = t.gettext
-<div id="migrate-guest-window" class="window modal-content">
- <div class="modal-header">
- <h4 class="modal-title" id="migrateModalLabel">$_("Migrate a Guest")</h4>
- </div>
- <div id="migrateInfo" class="modal-body">
- <div class="alert alert-warning" role="alert">Disclaimer: This process cannot be stopped after started,
- can take a long time to complete and will turn off the VM on this Hypervisor when it is successfully
- migrated to the remote destination.
- </div>
- <div class="form-group">
- <label for="remoteHostName">$_("Remote Server")</label>
- <input type="text" class="form-control" id="remoteHostName" />
- <p class="help-block">
- <i class="fa fa-info-circle"></i> $_("IP Address or Hostname")</p>
- </div>
- <div class="alert alert-info" role="alert">The following fields are optional. Fill them if you want Kimchi to
- setup a password-less ssh session between the localhost and the remote host. The setup process will only
- be successful if the user has 'SUDO ALL' permission in the remote machine.
+<!DOCTYPE html>
+<html>
+<body>
+ <div id="migrate-guest-window" class="window modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title" id="migrateModalLabel">$_("Migrate a Guest")</h4>
</div>
- <div class="form-group">
- <label for="user">$_("User")</label>
- <input type="text" class="form-control" id="user" />
- <p class="help-block">
- <i class="fa fa-info-circle"></i> $_("Username of the remote host")</p>
+ <div id="migrateInfo" class="modal-body">
+ <span id="alert-modal-container"></span>
+ <div class="alert alert-warning" role="alert">$_("Disclaimer: This process cannot be stopped after started, can take a long time to complete and will turn off the VM on this Hypervisor when it is successfully migrated to the remote destination.")</div>
+ <div class="form-group">
+ <label for="remoteHostName">$_("Remote Server")</label>
+ <input type="text" class="form-control" id="remoteHostName" />
+ <p class="help-block">
+ <i class="fa fa-info-circle"></i> $_("IP Address or Hostname")</p>
+ </div>
+ <div class="alert alert-info" role="alert">$_("The following fields are optional. Fill them if you want Kimchi to setup a password-less ssh session between the localhost and the remote host. The setup process will only be successful if the user has 'SUDO ALL' permission in the remote machine.")</div>
+ <div class="form-group">
+ <label for="username">$_("User")</label>
+ <input type="text" class="form-control" id="username" />
+ <p class="help-block">
+ <i class="fa fa-info-circle"></i> $_("Username of the remote host")</p>
+ </div>
+ <div class="form-group">
+ <label for="password">$_("Password")</label>
+ <input type="password" class="form-control" id="password" />
+ <p class="help-block">
+ <i class="fa fa-info-circle"></i> $_("Password of the user in the remote host")</p>
+ </div>
+ <div class="form-group">
+ <input id="deleteVM" class="wok-checkbox" type="checkbox" value="" />
+ <label for="deleteVM" id="labelDeleteVM">$_("Delete this VM when the migration is completed") </label>
+ </div>
</div>
- <div class="form-group">
- <label for="password">$_("Password")</label>
- <input type="password" class="form-control" id="password" />
- <p class="help-block">
- <i class="fa fa-info-circle"></i> $_("Password of the user in the remote host")</p>
+ <div class="modal-footer">
+ <button type="submit" id="migrateFormOk" class="btn btn-default">$_("Start")</button>
+ <button type="button" id="migrateFormCancel" data-dismiss="modal" class="btn btn-default">$_("Cancel")</button>
</div>
- <div class="form-group">
- <input id="deleteVM" class="wok-checkbox" type="checkbox" value="" />
- <label for="deleteVM" id="labelDeleteVM">$_("Delete this VM when the migration is completed") </label>
- </div>
- </div>
- <div class="modal-footer">
- <button type="submit" id="migrateFormOk" class="btn btn-default">$_("Start")</button>
- <button type="button" id="migrateFormCancel" data-dismiss="modal" class="btn btn-default">$_("Cancel")</button>
</div>
-</div>
-
+ <script>
+ kimchi.guest_livemigration_main();
+ </script>
+</body>
+</html>
diff --git a/ui/pages/guests.html.tmpl b/ui/pages/guests.html.tmpl
index 66a6e00..97ee17c 100644
--- a/ui/pages/guests.html.tmpl
+++ b/ui/pages/guests.html.tmpl
@@ -44,7 +44,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
- </div>
+ </div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="toolbar">
<ul class="nav navbar-nav navbar-right tools" display="none">
@@ -60,7 +60,7 @@
<label for="guests-filter" class="sr-only">$_("Filter"):</label>
<input type="text" class="filter form-control" placeholder="$_("Filter")">
</div>
- </div>
+ </div>
<div id="alert-container"></div>
<div id="guestListField" style="display: none">
<ul class="wok-guest-list">
diff --git a/ui/pages/i18n.json.tmpl b/ui/pages/i18n.json.tmpl
index d356437..bee3ad1 100644
--- a/ui/pages/i18n.json.tmpl
+++ b/ui/pages/i18n.json.tmpl
@@ -43,6 +43,8 @@
"KCHAPI6007M": "$_("Save")",
"KCHAPI6008M": "$_("Creating...")",
"KCHAPI6009M": "$_("Cloning...")",
+ "KCHAPI6010M": "$_("Migrating...")",
+ "KCHAPI6011M": "$_("Start")",
"KCHTMPL6001W": "$_("No ISO found")",
--
1.9.3
More information about the Kimchi-devel
mailing list