
From: Hongliang Wang <hlwang@linux.vnet.ibm.com> Connect download/upload volume window with storage pool add button. Signed-off-by: Hongliang Wang <hlwang@linux.vnet.ibm.com> Signed-off-by: Aline Manera <alinefm@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