[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