
- This patch implements necessary changes in frontend to allow users to edit and add extra disks to a chosen Template. - This patch also refactor the UI code in order to avoid lots of backend calls, improving performance. - Template disks data saved in objectstore have new fields: * 'size' is always recorded, even for ISCSI/SCSI types; * 'storagepooltype' is always recorded; * example: "disks":[ { "index":0, "format":"raw", "storagepooltype":"iscsi", "volume":"unit:0:0:2", "storagepool":"/plugins/kimchi/storagepools/test-iscsi", "size":7 }, { "index":1, "format":"qcow2", "storagepooltype":"dir", "storagepool":"/plugins/kimchi/storagepools/default", "size":3 } ] Signed-off-by: Rodrigo Trujillo <rodrigo.trujillo@linux.vnet.ibm.com> --- .../kimchi/ui/js/src/kimchi.template_edit_main.js | 246 ++++++++++----------- .../kimchi/ui/pages/template-edit.html.tmpl | 5 +- 2 files changed, 124 insertions(+), 127 deletions(-) diff --git a/src/wok/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js b/src/wok/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js index 5b77892..dfe770b 100644 --- a/src/wok/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js +++ b/src/wok/plugins/kimchi/ui/js/src/kimchi.template_edit_main.js @@ -22,7 +22,6 @@ kimchi.template_edit_main = function() { var origNetworks; var templateDiskSize; $('#template-name', templateEditMain).val(kimchi.selectedTemplate); - //templateEditMain.tabs(); $('#edit-template-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) { var target = $(this).attr('href'); @@ -68,134 +67,132 @@ kimchi.template_edit_main = function() { return false; } enableSpice(); + var initStorage = function(result) { - var scsipools = {}; + // Gather storage pool data + var storagePoolsInfo = new Object(); + $.each(result, function(index, pool) { + if (pool.state === 'active' && pool.type != 'kimchi-iso') { + if (pool.type === 'iscsi' || pool.type === 'scsi') { + volumes = new Object(); + kimchi.listStorageVolumes(pool.name, function(vols) { + $.each(vols, function(i, vol) { + storagePoolsInfo[pool.name + "/" + vol.name] = { + 'type' : pool.type, + 'volSize': vol.capacity / Math.pow(1024, 3)}; + }); + }, null, true); + } else { + storagePoolsInfo[pool.name] = { 'type' : pool.type }; + } + } + }); + var addStorageItem = function(storageData) { var thisName = storageData.storageName; + // Compatibility with old versions + if (storageData.storageVolume) { + storageData.storageDisk = storagePoolsInfo[thisName].volSize; + } + if (!storageData.storageType) { + storageData.storageType = storagePoolsInfo[thisName].type; + } + var nodeStorage = $.parseHTML(wok.substitute($('#template-storage-pool-tmpl').html(), storageData)); $('.template-tab-body', '#form-template-storage').append(nodeStorage); + var storageRow = '#storageRow' + storageData.storageIndex; + var storageOptions = ''; - var scsiOptions = ''; - $('#selectStorageName').find('option').remove(); - $.each(result, function(index, storageEntities) { - if((storageEntities.state === 'active') && (storageEntities.type != 'kimchi-iso')) { - if(storageEntities.type === 'iscsi' || storageEntities.type === 'scsi') { - kimchi.listStorageVolumes(storageEntities.name, function(currentVolume) { - $.each(currentVolume, function(indexSCSI, scsiEntities) { - var tmpPath = storageEntities.name + '/' + scsiEntities.name; - var isSlected = tmpPath === thisName ? ' selected' : ''; - scsiOptions += '<option' + isSlected + '>' + tmpPath + '</option>'; - }); - $('#selectStorageName').append(scsiOptions); - }, function() {}); - } else { - var isSlected = storageEntities.name === thisName ? ' selected' : ''; - storageOptions += '<option' + isSlected + '>' + storageEntities.name + '</option>'; - } - } + $.each(storagePoolsInfo, function(poolName, value) { + storageOptions += '<option value="' + poolName + '">' + poolName + '</option>'; }); - $('#selectStorageName').append(storageOptions); - $('select','#form-template-storage').selectpicker(); + + $(storageRow + ' #selectStorageName').append(storageOptions); + $(storageRow + ' #selectStorageName').val(storageData.storageName); + $(storageRow + ' #selectStorageName').selectpicker(); + + if (storageData.storageType === 'iscsi' || storageData.storageType === 'scsi') { + $(storageRow + ' .template-storage-disk').attr('readonly', true).prop('disabled', true); + $(storageRow + ' #diskFormat').val('raw'); + $(storageRow + ' #diskFormat').prop('disabled', true).change(); + } else if (storageData.storageType === 'logical') { + $(storageRow + ' #diskFormat').val('raw'); + $(storageRow + ' #diskFormat').prop('disabled', true).change(); + } // Set disk format if (isImageBasedTemplate()) { - $('#diskFormat').val('qcow2'); - $('#diskFormat').prop('disabled', 'disabled'); + $(storageRow + ' #diskFormat').val('qcow2'); + $(storageRow + ' #diskFormat').prop('disabled', 'disabled'); } else { - $('#diskFormat').val(storageData.storageDiskFormat); - $('#diskFormat').on('change', function() { - $('.template-storage-disk-format').val($(this).val()); + $(storageRow + ' #diskFormat').val(storageData.storageDiskFormat); + $(storageRow + ' #diskFormat').on('change', function() { + $(storageRow + ' .template-storage-disk-format').val($(this).val()); }); } + $(storageRow + ' #diskFormat').selectpicker(); - $('#selectStorageName').change(function() { - var selectedItem = $(this).parent().parent(); - var tempStorageNameFull = $(this).val(); - var tempName = tempStorageNameFull.split('/'); - var tempStorageName = tempName[0]; - $('.template-storage-name').val(tempStorageNameFull); - kimchi.getStoragePool(tempStorageName, function(info) { - tempType = info.type; - selectedItem.find('.template-storage-type').val(tempType); - if (tempType === 'iscsi' || tempType === 'scsi') { - kimchi.getStoragePoolVolume(tempStorageName, tempName[tempName.length-1], function(info) { - volSize = info.capacity / Math.pow(1024, 3); - $('.template-storage-disk', selectedItem).attr('readonly', true).val(volSize); - if (!isImageBasedTemplate()) { - $('#diskFormat').val('raw'); - $('#diskFormat').prop('disabled', true).change(); - } - }); - } else if (tempType === 'logical') { - $('.template-storage-disk', selectedItem).attr('readonly', false); - if (!isImageBasedTemplate()) { - $('#diskFormat').val('raw'); - $('#diskFormat').prop('disabled', true).change(); - } - } else { - $('.template-storage-disk', selectedItem).attr('readonly', false); - if ($('#diskFormat').prop('disabled') == true && - !isImageBasedTemplate()) { - $('#diskFormat').val('qcow2'); - $('#diskFormat').prop('disabled', false).change(); - } - } - }); + $('.delete', '#form-template-storage').on( "click",function(event) { + event.preventDefault(); + $(this).parent().parent().remove(); }); - }; - - if ((origDisks && origDisks.length) && (origPool && origPool.length)) { - splitPool = origPool.split('/'); - var defaultPool = splitPool[splitPool.length-1]; - var defaultType; - kimchi.getStoragePool(defaultPool, function(info) { - defaultType = info.type; - $.each(origDisks, function(index, diskEntities) { - var storageNodeData = { - viewMode : '', - editMode : 'hide', - storageName : defaultPool, - storageType : defaultType, - storageDisk : diskEntities.size, - storageDiskFormat : diskEntities.format ? diskEntities.format : 'qcow2' + $(storageRow + ' #selectStorageName').change(function() { + var poolType = storagePoolsInfo[$(this).val()].type; + $(storageRow + ' .template-storage-name').val($(this).val()); + $(storageRow + ' .template-storage-type').val(poolType); + if (poolType === 'iscsi' || poolType === 'scsi') { + $(storageRow + ' .template-storage-disk').attr('readonly', true).prop('disabled', true).val(storagePoolsInfo[$(this).val()].volSize); + if (!isImageBasedTemplate()) { + $(storageRow + ' #diskFormat').val('raw').prop('disabled', true).change(); } - - if (diskEntities.volume) { - kimchi.getStoragePoolVolume(defaultPool, diskEntities.volume, function(info) { - var volSize = info.capacity / Math.pow(1024, 3); - var nodeData = storageNodeData - nodeData.storageName = defaultPool + '/' + diskEntities.volume; - nodeData.storageDisk = volSize; - addStorageItem(nodeData); - $('.template-storage-disk').attr('readonly', true); - $('#diskFormat').val('raw'); - $('#diskFormat').prop('disabled', true).change(); - }); - } else if (defaultType === 'logical') { - addStorageItem(storageNodeData); - $('#diskFormat').val('raw'); - $('#diskFormat').prop('disabled', true).change(); - } else { - addStorageItem(storageNodeData); + } else if (poolType === 'logical') { + $(storageRow + ' .template-storage-disk').attr('readonly', false).prop('disabled', false); + if (!isImageBasedTemplate()) { + $(storageRow + ' #diskFormat').val('raw').prop('disabled', true).change(); } - }); + } else { + $(storageRow + ' .template-storage-disk').attr('readonly', false).prop('disabled', false); + if ($(storageRow + ' #diskFormat').prop('disabled') == true && !isImageBasedTemplate()) { + $(storageRow + ' #diskFormat').val('qcow2').prop('disabled', false).change(); + } + } + $(storageRow + ' #diskFormat').selectpicker('refresh'); + }); + }; // End of addStorageItem funtion + + if ((origDisks && origDisks.length) && (origPool && origPool.length)) { + origDisks.sort(function(a, b){return a.index-b.index}); + $.each(origDisks, function(index, diskEntities) { + var defaultPool = diskEntities.storagepool ? diskEntities.storagepool.split('/').pop() : origPool.split('/').pop() + var storageNodeData = { + storageIndex : diskEntities.index, + storageName : diskEntities.volume ? defaultPool + '/' + diskEntities.volume : defaultPool, + storageType : diskEntities.storagepooltype, + storageDisk : diskEntities.size, + storageDiskFormat : diskEntities.format ? diskEntities.format : 'qcow2', + storageVolume : diskEntities.volume + } + addStorageItem(storageNodeData); }); } + var storageID = origDisks.length -1; $('#template-edit-storage-add-button').on("click", function(event) { event.preventDefault(); + storageID = storageID + 1; var storageNodeData = { - viewMode : 'hide', - editMode : '', - storageName : 'null', + storageName : 'default', storageType : 'dir', - storageDisk : '10' + storageDisk : '10', + storageDiskFormat : 'qcow2', + storageIndex : storageID } addStorageItem(storageNodeData); }); }; + var initInterface = function(result) { var networkItemNum = 0; var addInterfaceItem = function(networkData) { @@ -235,6 +232,7 @@ kimchi.template_edit_main = function() { }); }); }; + var initProcessor = function(){ var setCPUValue = function(){ if(!$('#cores').hasClass("invalid-field")&&$('#cores').val()!=""){ @@ -278,36 +276,32 @@ kimchi.template_edit_main = function() { }; kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate); - $('#tmpl-edit-button-save').on('click', function() { - var editableFields = [ 'name', 'memory', 'disks', 'graphics']; + var editableFields = [ 'name', 'memory', 'graphics']; var data = {}; - //Fix me: Only support one storage pool now - var storages = $('.template-tab-body .item', '#form-template-storage'); - var tempName = $('.template-storage-name', storages).val(); - var tmpItem = $('#form-template-storage .item'); - tempName = tempName.split('/'); - var tempNameHead = tempName[0]; - var tempNameTail = tempNameHead; - if($('.template-storage-type', tmpItem).val() === 'iscsi' || $('.template-storage-type', tmpItem).val() == 'scsi') { - tempNameTail = tempName[tempName.length-1]; - } - tempName = '/plugins/kimchi/storagepools/' + tempNameHead; - data['storagepool'] = tempName; - $.each(editableFields, function(i, field) { - /* Support only 1 disk at this moment */ - if (field == 'disks') { - if($('.template-storage-type', tmpItem).val() === 'iscsi' || $('.template-storage-type', tmpItem).val() == 'scsi') { - origDisks[0]['size'] && delete origDisks[0]['size']; - origDisks[0]['volume'] = tempNameTail; - } else { - origDisks[0]['volume'] && delete origDisks[0]['volume']; - origDisks[0].size = Number($('.template-storage-disk', tmpItem).val()); - } - origDisks[0].format = $('.template-storage-disk-format', tmpItem).val(); - data[field] = origDisks; + var disks = $('.template-tab-body .item', '#form-template-storage'); + var disksForUpdate = new Array(); + $.each(disks, function(index, diskEntity) { + var newDisk = { + 'index' : index, + 'storagepool' : '/plugins/kimchi/storagepools/' + $(diskEntity).find('.template-storage-name').val(), + 'size' : Number($(diskEntity).find('.template-storage-disk').val()), + 'format' : $(diskEntity).find('.template-storage-disk-format').val() + }; + + var storageType = $(diskEntity).find('.template-storage-type').val(); + newDisk['storagepooltype'] = storageType; + + if(storageType === 'iscsi' || storageType === 'scsi') { + newDisk['volume'] = newDisk['storagepool'].split('/').pop(); + newDisk['storagepool'] = newDisk['storagepool'].slice(0, newDisk['storagepool'].lastIndexOf('/')); } - else if (field == 'graphics') { + disksForUpdate.push(newDisk); + }); + data.disks = disksForUpdate; + + $.each(editableFields, function(i, field) { + if (field == 'graphics') { var type = $('#form-template-general [name="' + field + '"]').val(); data[field] = {'type': type}; } diff --git a/src/wok/plugins/kimchi/ui/pages/template-edit.html.tmpl b/src/wok/plugins/kimchi/ui/pages/template-edit.html.tmpl index 59a2cfa..dc6b762 100644 --- a/src/wok/plugins/kimchi/ui/pages/template-edit.html.tmpl +++ b/src/wok/plugins/kimchi/ui/pages/template-edit.html.tmpl @@ -156,7 +156,7 @@ kimchi.template_edit_main(); </script> <script id="template-storage-pool-tmpl" type="text/html"> - <div class='item'> + <div id="storageRow{storageIndex}" class='item'> <span class="template-storage-cell storage-pool"> <input class="template-storage-name" value={storageName} type="text" style="display:none" /> <select id="selectStorageName"></select> @@ -182,6 +182,9 @@ <option value="vpc">vpc</option> </select> </span> + <span class="pull-right"> + <button class="delete btn-primary btn"><i class="fa fa-minus-circle"></i> $_("Delete")</button> + </span> </div> </script> <script id="template-interface-tmpl" type="text/html"> -- 2.1.0