[Kimchi-devel] [PATCH 4/5] Storage Pool Add Volume UI: Connect the Feature in Storage Tab

Aline Manera alinefm at linux.vnet.ibm.com
Mon Sep 15 21:28:52 UTC 2014


From: Hongliang Wang <hlwang at linux.vnet.ibm.com>

Connect download/upload volume window with storage pool add button.

Signed-off-by: Hongliang Wang <hlwang at linux.vnet.ibm.com>
Signed-off-by: Aline Manera <alinefm at linux.vnet.ibm.com>
---
 ui/css/theme-default/storage.css |  31 ++++++-
 ui/js/src/kimchi.storage_main.js | 196 ++++++++++++++++++++++++++++++++++-----
 ui/pages/tabs/storage.html.tmpl  |  12 ++-
 3 files changed, 213 insertions(+), 26 deletions(-)

diff --git a/ui/css/theme-default/storage.css b/ui/css/theme-default/storage.css
index f635c2f..e0ab290 100644
--- a/ui/css/theme-default/storage.css
+++ b/ui/css/theme-default/storage.css
@@ -336,7 +336,6 @@
     float: left;
     padding: 4px;
     margin-bottom: 5px;
-    height: 40px;
     width: 130px;
 }
 
@@ -622,3 +621,33 @@
 #iSCSITarget input {
     width: 493px;
 }
+
+/* Progress bar */
+.volume-progress {
+    clear: both;
+    width: 140px;
+}
+
+.volume-progress .progress-bar-outer {
+    background: #ccc;
+    height: 4px;
+    overflow: hidden;
+    width: 100%;
+}
+
+.volume-progress .progress-bar-inner {
+    background: #090;
+    height: 100%;
+    width: 0%;
+}
+
+.volume-progress .progress-label {
+    color: #999;
+    font-size: 10px;
+    line-height: 16px;
+}
+
+.volume-progress .progress-transferred {
+    float: right;
+}
+/* End of Progress bar */
diff --git a/ui/js/src/kimchi.storage_main.js b/ui/js/src/kimchi.storage_main.js
index ae3f963..28b2b58 100644
--- a/ui/js/src/kimchi.storage_main.js
+++ b/ui/js/src/kimchi.storage_main.js
@@ -42,7 +42,6 @@ kimchi.doListStoragePools = function() {
     }, function(err) {
         kimchi.message.error(err.responseJSON.reason);
     });
-
 }
 
 kimchi.storageBindClick = function() {
@@ -79,6 +78,19 @@ kimchi.storageBindClick = function() {
         }
     });
 
+    $('.pool-add-volume').each(function(index) {
+        var canAddVolume =
+            $(this).data('stat') === 'active' &&
+            $(this).data('type') !== 'iscsi' &&
+            $(this).data('type') !== 'scsi';
+        if(canAddVolume) {
+            $(this).show();
+        }
+        else {
+            $(this).hide();
+        }
+    });
+
     if(kimchi.tabMode['storage'] === 'admin') {
         $('.pool-delete').on('click', function(event) {
             var $pool = $(this);
@@ -135,6 +147,12 @@ kimchi.storageBindClick = function() {
             }
         });
 
+        $('.pool-add-volume').on('click', function(event) {
+            var poolName = $(this).data('name');
+            kimchi.selectedSP = poolName;
+            kimchi.window.open('storagepool-add-volume.html');
+        });
+
         $('.storage-action').on('click', function() {
             var storage_action = $(this);
             var deleteButton = storage_action.find('.pool-delete');
@@ -149,10 +167,6 @@ kimchi.storageBindClick = function() {
             $("#logicalPoolExtend").dialog("option", "poolName", $(this).data('name'));
             $("#logicalPoolExtend").dialog("open");
         });
-
-        $('#volume-doAdd').on('click', function() {
-            kimchi.window.open('storagevolume-add.html');
-        });
     }
 
     $('.storage-li').on('click', function(event) {
@@ -173,29 +187,90 @@ kimchi.storageBindClick = function() {
     });
 }
 
+kimchi._generateVolumeHTML = function(volume) {
+    if(volume['type'] === 'kimchi-iso') {
+        return '';
+    }
+    var volumeHtml = $('#volumeTmpl').html();
+    volume.capacity = kimchi.changetoProperUnit(volume.capacity,1);
+    volume.allocation = kimchi.changetoProperUnit(volume.allocation,1);
+    return kimchi.substitute(volumeHtml, volume);
+};
+
 kimchi.doListVolumes = function(poolObj) {
-    var volumeDiv = $('#volume' + poolObj.data('name'));
+    var poolName = poolObj.data('name')
+
+    var getOngoingVolumes = function() {
+        var result = {}
+        var filter = 'status=running&target_uri=' + encodeURIComponent('^/storagepools/' + poolName + '/*')
+        kimchi.getTasksByFilter(filter, function(tasks) {
+            for(var i = 0; i < tasks.length; i++) {
+                var volumeName = tasks[i].target_uri.split('/').pop();
+                result[volumeName] = tasks[i];
+
+                if(kimchi.trackingTasks.indexOf(tasks[i].id) >= 0) {
+                    continue;
+                }
+
+                kimchi.trackTask(tasks[i].id, function(result) {
+                    kimchi.topic('kimchi/volumeTransferFinished').publish(result);
+                }, function(result) {
+                    kimchi.topic('kimchi/volumeTransferError').publish(result);
+                }, function(result) {
+                    kimchi.topic('kimchi/volumeTransferProgress').publish(result);
+                });
+            }
+        }, null, true);
+        return result;
+    };
+
+    var volumeDiv = $('#volume' + poolName);
+    $(volumeDiv).empty();
     var slide = poolObj.next('.volumes');
     var handleArrow = poolObj.children().last().children();
-    kimchi.listStorageVolumes(poolObj.data('name'), function(result) {
-        var volumeHtml = $('#volumeTmpl').html();
-        if (result) {
-            if (result.length) {
-                var listHtml = '';
-                $.each(result, function(index, value) {
-                    value.poolname = poolObj.data('name');
-                    value.capacity = kimchi.changetoProperUnit(value.capacity,1);
-                    value.allocation = kimchi.changetoProperUnit(value.allocation,1);
-                    listHtml += kimchi.substitute(volumeHtml, value);
-                });
-                volumeDiv.html(listHtml);
-            } else {
-                volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>");
+
+    kimchi.listStorageVolumes(poolName, function(result) {
+        var listHtml = '';
+        var ongoingVolumes = [];
+        var ongoingVolumesMap = getOngoingVolumes();
+        $.each(ongoingVolumesMap, function(volumeName, task) {
+            ongoingVolumes.push(volumeName)
+            var volume = {
+                poolName: poolName,
+                ref_cnt: 0,
+                capacity: 0,
+                name: volumeName,
+                format: '',
+                bootable: null,
+                os_distro: '',
+                allocation: 0,
+                os_version: '',
+                path: '',
+                type: 'file'
+            };
+            listHtml += kimchi._generateVolumeHTML(volume);
+        });
+
+        $.each(result, function(index, value) {
+            if (ongoingVolumes.indexOf(value.name) == -1) {
+                value.poolname = poolName;
+                listHtml += kimchi._generateVolumeHTML(value);
             }
-            poolObj.removeClass('in');
-            kimchi.changeArrow(handleArrow);
-            slide.slideDown('slow');
+        });
+
+        if (listHtml.length > 0) {
+            volumeDiv.html(listHtml);
+        } else {
+            volumeDiv.html("<div class='pool-empty'>" + i18n['KCHPOOL6002M'] + "</div>");
         }
+
+        $.each(ongoingVolumesMap, function(volumeName, task) {
+            kimchi.topic('kimchi/volumeTransferProgress').publish(task);
+        });
+
+        poolObj.removeClass('in');
+        kimchi.changeArrow(handleArrow);
+        slide.slideDown('slow');
     }, function(err) {
         kimchi.message.error(err.responseJSON.reason);
     });
@@ -255,7 +330,80 @@ kimchi.storage_main = function() {
     }
     kimchi.doListStoragePools();
     kimchi.initLogicalPoolExtend();
-}
+
+    kimchi.topic('kimchi/storageVolumeAdded').subscribe(function() {
+        pool = kimchi.selectedSP;
+        var poolNode = $('.storage-li[data-name="' + pool + '"]');
+        kimchi.doListVolumes(poolNode);
+    });
+
+    kimchi.topic('kimchi/volumeTransferProgress').subscribe(function(result) {
+        var extractProgressData = function(data) {
+            var sizeArray = /(\d+)\/(\d+)/g.exec(data) || [0, 0, 0];
+            var downloaded = sizeArray[1];
+            var percent = 0;
+            if(downloaded) {
+                var total = sizeArray[2];
+                if(!isNaN(total)) {
+                    percent = downloaded / total * 100;
+                }
+            }
+            var formatted = kimchi.formatMeasurement(downloaded);
+            var size = (1.0 * formatted['v']).toFixed(1) + formatted['s'];
+            return {
+                size: size,
+                percent: percent
+            };
+        };
+
+        var uriElements = result.target_uri.split('/');
+        var poolName = uriElements[2];
+        var volumeName = uriElements.pop();
+        var progress = extractProgressData(result['message']);
+        var size = progress['size'];
+        var percent = progress['percent'];
+
+        volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
+        $('.progress-bar-inner', volumeBox).css({
+            width: percent + '%'
+        });
+        $('.progress-transferred', volumeBox).text(size);
+        $('.volume-progress', volumeBox).removeClass('hidden');
+        $('.progress-status', volumeBox).text(i18n['KCHPOOL6014M']);
+    });
+
+    kimchi.topic('kimchi/volumeTransferFinished').subscribe(function(result) {
+        var uriElements = result.target_uri.split('/');
+        var poolName = uriElements[2];
+        var volumeName = uriElements.pop();
+        var volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
+        $('.volume-progress', volumeBox).addClass('hidden');
+        kimchi.getStoragePoolVolume(poolName, volumeName, function(volume) {
+            var html = kimchi._generateVolumeHTML(volume);
+            $(volumeBox).replaceWith(html);
+        }, function(err) {
+            kimchi.message.error(err.responseJSON.reason);
+        });
+    });
+
+    kimchi.topic('kimchi/volumeTransferError').subscribe(function(result) {
+        // Error message from Async Task status
+        if (result['message']) {
+            var errText = result['message'];
+        }
+        // Error message from standard kimchi exception
+        else {
+            var errText = result['responseJSON']['reason'];
+        }
+        result && kimchi.message.error(errText);
+
+        var uriElements = result.target_uri.split('/');
+        var poolName = uriElements[2];
+        var volumeName = uriElements.pop();
+        volumeBox = $('#volume' + poolName + ' [data-volume-name="' + volumeName + '"]');
+        $('.progress-status', volumeBox).text(i18n['KCHPOOL6015M']);
+    });
+};
 
 kimchi.changeArrow = function(obj) {
     if ($(obj).hasClass('arrow-down')) {
diff --git a/ui/pages/tabs/storage.html.tmpl b/ui/pages/tabs/storage.html.tmpl
index 87205bd..523f480 100644
--- a/ui/pages/tabs/storage.html.tmpl
+++ b/ui/pages/tabs/storage.html.tmpl
@@ -82,6 +82,7 @@
                     <div class="popover actionsheet right-side" style="width: 250px">
                         <button class="button-big pool-deactivate" data-stat="{state}" data-name="{name}" data-persistent="{persistent}"><span class="text">$_("Deactivate")</span></button>
                         <button class="button-big pool-activate" data-stat="{state}" data-name="{name}"><span class="text">$_("Activate")</span></button>
+                        <button class="button-big pool-add-volume" data-stat="{state}" data-name="{name}" data-type="{type}"><span class="text">$_("Add Volume")</span></button>
                         <button class="button-big pool-extend {enableExt}" data-stat="{state}" data-name="{name}"><span class="text">$_("Extend")</span></button>
                         <button class="button-big red pool-delete" data-stat="{state}" data-name="{name}"><span class="text">$_("Undefine")</span></button>
                     </div>
@@ -98,11 +99,20 @@
     </li>
 </script>
 <script id="volumeTmpl" type="html/text">
-        <div class="volume-box white-box">
+        <div class="volume-box white-box" data-volume-name="{name}">
             <div class="storage-icon volume-default icon-{format} ">
             </div>
             <div class="volume-title">
                 <div class="volume-name" title="{name}">{name}</div>
+                <div class="volume-progress hidden">
+                    <div class="progress-bar-outer">
+                        <div class="progress-bar-inner"></div>
+                    </div>
+                    <div class="progress-label">
+                        <span class="progress-status"></span>
+                        <span class="progress-transferred"></span>
+                    </div>
+                </div>
             </div>
             <div class="volume-setting">
             </div>
-- 
1.9.3




More information about the Kimchi-devel mailing list