[Kimchi-devel] [PATCH 2/2 - v2] UI - Implement multiple disks support in Template edit window
Aline Manera
alinefm at linux.vnet.ibm.com
Mon Nov 16 20:15:47 UTC 2015
On 16/11/2015 18:12, Aline Manera wrote:
>
>
> On 12/11/2015 10:11, Rodrigo Trujillo wrote:
>> - 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;
>
> Please, update docs/API.md accordingly. Also add backend tests to
> verify the new fields in the Template object.
And also API.json to reflect the disks update.
>
>> * 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 at 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">
>
> _______________________________________________
> Kimchi-devel mailing list
> Kimchi-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/kimchi-devel
>
More information about the Kimchi-devel
mailing list