[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:12:48 UTC 2015



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.

>    * 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">




More information about the Kimchi-devel mailing list