[Kimchi-devel] [v2] UI: Clone Guest
Yu Xin Huo
huoyuxin at linux.vnet.ibm.com
Tue Oct 28 08:58:53 UTC 2014
On 10/28/2014 3:18 AM, Paulo Ricardo Paz Vital wrote:
> I'd like to do two suggestions:
> 1) Add a progress bar just below the 'Cloning..." text to show the
> cloning progress - libvirt provides this info; and
I assume the progress is overall cloning progress. It is helpful, let me
know where to get it from API response.
> 2) Add a warning screen when user select to clone a VM informing that
> the new virtual disk will be located in the default storage pool if the
> VM is using a iSCSI storage pool and/or the storage pool of the VM to be
> cloned doesn't have enough space in disk. It's a informative warning
> that must be displayed every time that a VM is choosed to be cloned
> (like when user select to execute a Power Off of some running guest).
If it is just a static alert message, I think it is better to put it
into help doc.
1. This alert message is only valuable when user first time clone a
guest, once he/she got to know that, it is completely redundant for
daily operations.
2. Clone is not an operation like 'Delete' that will lead to harmful,
unrecoverable result. If user dislike it after cloning, he can delete
the cloned guest.
3. The default clone is to pursue truly desired outcome for user to have
a new guest with rid of any noisy distraction.
As we have discussed, default clone is not functional enough and a
'Custom Clone' will be added. in 'Custom Clone'
A dialog will popup with all customization options for user to select,
including select the target pool for each virtual disk of the guest.
>
> I know that the second topic was discussed in previous scrum meetings,
> but it's important alert the user about the backend operations.
>
> Thanks and best regards,
> -- Paulo Ricardo Paz Vital <pvital at linux.vnet.ibm.com> IBM Linux
> Technology Center
>> >From: Yu Xin Huo<huoyuxin at linux.vnet.ibm.com>
>> >
>> >Signed-off-by: Yu Xin Huo<huoyuxin at linux.vnet.ibm.com>
>> >---
>> > ui/css/theme-default/list.css | 18 ++++++++++
>> > ui/js/src/kimchi.api.js | 17 ++++++++-
>> > ui/js/src/kimchi.guest_main.js | 73 +++++++++++++++++++++++++++++++++++----
>> > ui/pages/guest.html.tmpl | 6 +++-
>> > 4 files changed, 103 insertions(+), 11 deletions(-)
>> >
>> >diff --git a/ui/css/theme-default/list.css b/ui/css/theme-default/list.css
>> >index 8ffee69..fc3017b 100644
>> >--- a/ui/css/theme-default/list.css
>> >+++ b/ui/css/theme-default/list.css
>> >@@ -275,3 +275,21 @@
>> > text-shadow: -1px -1px 1px #ccc, 1px 1px 1px #fff;
>> > padding-left: 10px;
>> > }
>> >+
>> >+.guest-clone {
>> >+ margin: 10px;
>> >+}
>> >+
>> >+.guest-clone .icon {
>> >+ background: url('../../images/theme-default/loading.gif') no-repeat;
>> >+ display: inline-block;
>> >+ width: 20px;
>> >+ height: 20px;
>> >+ vertical-align: middle;
>> >+}
>> >+
>> >+.guest-clone .text {
>> >+ color: #666666;
>> >+ margin-left: 5px;
>> >+ text-shadow: -1px -1px 1px #CCCCCC, 1px 1px 1px #FFFFFF;
>> >+}
>> >diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
>> >index 5895a07..2f90219 100644
>> >--- a/ui/js/src/kimchi.api.js
>> >+++ b/ui/js/src/kimchi.api.js
>> >@@ -695,10 +695,10 @@ var kimchi = {
>> > }, 2000);
>> > break;
>> > case 'finished':
>> >- suc(result);
>> >+ suc && suc(result);
>> > break;
>> > case 'failed':
>> >- err(result);
>> >+ err && err(result);
>> > break;
>> > default:
>> > break;
>> >@@ -1233,5 +1233,18 @@ var kimchi = {
>> > success : suc,
>> > error : err
>> > });
>> >+ },
>> >+
>> >+ cloneGuest: function(vm, suc, err) {
>> >+ kimchi.requestJSON({
>> >+ url : kimchi.url + 'vms/'+encodeURIComponent(vm)+"/clone",
>> >+ type : 'POST',
>> >+ contentType : 'application/json',
>> >+ dataType : 'json',
>> >+ success : suc,
>> >+ error : err ? err : function(data) {
>> >+ kimchi.message.error(data.responseJSON.reason);
>> >+ }
>> >+ });
>> > }
>> > };
>> >diff --git a/ui/js/src/kimchi.guest_main.js b/ui/js/src/kimchi.guest_main.js
>> >index dbe8753..ecc3b7a 100644
>> >--- a/ui/js/src/kimchi.guest_main.js
>> >+++ b/ui/js/src/kimchi.guest_main.js
>> >@@ -15,6 +15,34 @@
>> > * See the License for the specific language governing permissions and
>> > * limitations under the License.
>> > */
>> >+kimchi.sampleGuestObject = {
>> >+ "name": "",
>> >+ "uuid": "",
>> >+ "state": "shutoff",
>> >+ "persistent": true,
>> >+ "icon": null,
>> >+ "cpus": 0,
>> >+ "memory": 0,
>> >+ "stats": {
>> >+ "net_throughput": 0,
>> >+ "io_throughput_peak": 100,
>> >+ "cpu_utilization": 0,
>> >+ "io_throughput": 0,
>> >+ "net_throughput_peak": 100
>> >+ },
>> >+ "screenshot": null,
>> >+ "graphics": {
>> >+ "passwd": null,
>> >+ "passwdValidTo": null,
>> >+ "type": "vnc",
>> >+ "port": null,
>> >+ "listen": "127.0.0.1"
>> >+ },
>> >+ "users": [],
>> >+ "groups": [],
>> >+ "access": "full"
>> >+};
>> >+
>> >
>> > kimchi.vmstart = function(event) {
>> > var button=$(this);
>> >@@ -173,8 +201,24 @@ kimchi.listVmsAuto = function() {
>> > if (kimchi.vmTimeout) {
>> > clearTimeout(kimchi.vmTimeout);
>> > }
>> >+ var getCloningGuests = function(){
>> >+ var guests = [];
>> >+ kimchi.getTasksByFilter('status=running&target_uri='+encodeURIComponent('^/vms/*'), function(tasks) {
>> >+ for(var i=0;i<tasks.length;i++){
>> >+ var guestUri = tasks[i].target_uri;
>> >+ var guestName = guestUri.substring(guestUri.lastIndexOf('/')+1, guestUri.length);
>> >+ guests.push($.extend({}, kimchi.sampleGuestObject, {name: guestName, isCloning: true}));
>> >+ if(kimchi.trackingTasks.indexOf(tasks[i].id)==-1)
>> >+ kimchi.trackTask(tasks[i].id, null, function(err){
>> >+ kimchi.message.error(err.message);
>> >+ }, null);
>> >+ }
>> >+ }, null, true);
>> >+ return guests;
>> >+ };
>> > kimchi.listVMs(function(result, textStatus, jqXHR) {
>> > if (result && textStatus=="success") {
>> >+ result = getCloningGuests().concat(result);
>> > if(result.length) {
>> > var listHtml = '';
>> > var guestTemplate = kimchi.guestTemplate;
>> >@@ -233,14 +277,16 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
>> > imgLoad.attr('src',load_src);
>> >
>> > //Link the stopped tile to the start action, the running tile to open the console
>> >- if (vmRunningBool) {
>> >- liveTile.off("click", kimchi.vmstart);
>> >- liveTile.on("click", kimchi.openVmConsole);
>> >- }
>> >- else {
>> >- liveTile.off("click", kimchi.openVmConsole);
>> >- liveTile.on("click", kimchi.vmstart);
>> >- liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
>> >+ if(!vmObject.isCloning){
>> >+ if (vmRunningBool) {
>> >+ liveTile.off("click", kimchi.vmstart);
>> >+ liveTile.on("click", kimchi.openVmConsole);
>> >+ }
>> >+ else {
>> >+ liveTile.off("click", kimchi.openVmConsole);
>> >+ liveTile.on("click", kimchi.vmstart);
>> >+ liveTile.hover(function(event){$(this).find('.overlay').show()}, function(event){$(this).find('.overlay').hide()});
>> >+ }
>> > }
>> >
>> >
>> >@@ -257,6 +303,7 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
>> > //Setup the VM Actions
>> > var guestActions=result.find("div[name=guest-actions]");
>> > guestActions.find(".shutoff-disabled").prop('disabled', !vmRunningBool );
>> >+ guestActions.find(".running-disabled").prop('disabled', vmRunningBool );
>> >
>> > if (vmRunningBool) {
>> > guestActions.find(".running-hidden").hide();
>> >@@ -286,6 +333,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
>> > }
>> > guestActions.find("[name=vm-edit]").on({click : kimchi.vmedit});
>> > guestActions.find("[name=vm-delete]").on({click : kimchi.vmdelete});
>> >+ guestActions.find("[name=vm-clone]").click(function(){
>> >+ kimchi.cloneGuest($(this).closest('li[name=guest]').attr("id"), function(data){
>> >+ kimchi.listVmsAuto();
>> >+ });
>> >+ });
>> >
>> > //Maintain menu open state
>> > var actionMenu=guestActions.find("div[name=actionmenu]");
>> >@@ -293,6 +345,11 @@ kimchi.createGuestLi = function(vmObject, prevScreenImage, openMenu) {
>> > $('.popover', actionMenu).toggle();
>> > }
>> >
>> >+ if(vmObject.isCloning){
>> >+ guestActions.children().hide();
>> >+ result.find('.guest-clone').removeClass('hide-content');
>> >+ }
>> >+
>> > return result;
>> > };
>> >
>> >diff --git a/ui/pages/guest.html.tmpl b/ui/pages/guest.html.tmpl
>> >index 43fb350..74206fd 100644
>> >--- a/ui/pages/guest.html.tmpl
>> >+++ b/ui/pages/guest.html.tmpl
>> >@@ -26,6 +26,9 @@
>> > <div class="guest-general">
>> > <h2 class="title" title="{name}">{name}</h2>
>> > </div>
>> >+ <div class="guest-clone hide-content">
>> >+ <span class="icon"></span><span class="text">$_("Cloning")...</span>
>> >+ </div>
>> > </div>
>> > <div name="cpu_utilization" class="sortable">
>> > <div class="circleGauge"></div>
>> >@@ -56,7 +59,8 @@
>> > <span class="text">$_("Actions")</span><span class="arrow"></span>
>> > <div class="popover actionsheet right-side" style="width: 250px">
>> > <button class="button-big shutoff-disabled" name="vm-console" ><span class="text">$_("Connect")</span></button>
>> >- <button class="button-big running-disabled" name="vm-edit"><span class="text">$_("Edit")</span></button>
>> >+ <button class="button-big running-disabled" name="vm-clone"><span class="text">$_("Clone")</span></button>
>> >+ <button class="button-big" name="vm-edit"><span class="text">$_("Edit")</span></button>
>> > <button class="button-big shutoff-hidden" name="vm-reset"><span class="text">$_("Reset")</span></button>
>> > <button class="button-big shutoff-hidden" name="vm-shutdown"><span class="text">$_("Shut Down")</span></button>
>> > <button class="button-big running-hidden" name="vm-start"><span class="text">$_("Start")</span></button>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20141028/f47525fb/attachment.html>
More information about the Kimchi-devel
mailing list