[Kimchi-devel] [PATCH] [Kimchi] Introducing s390x UI Storage module for Edit Template under virtualization

Aline Manera alinefm at linux.vnet.ibm.com
Mon Sep 12 21:02:52 UTC 2016



On 09/09/2016 04:23 AM, rajgupta at linux.vnet.ibm.com wrote:
> From: Rajat Gupta <rajgupta at linux.vnet.linux.com>
>
> Introducing s390x UI Storage module for Edit Template under virtualization
>
> Signed-off-by: Rajat Gupta <rajgupta at linux.vnet.linux.com>
> ---
>   ui/css/kimchi.css                      |  12 +-
>   ui/css/src/modules/_templates.scss     |  10 +-
>   ui/js/src/kimchi.template_edit_main.js | 277 ++++++++++++++++++++++++++++-----
>   ui/pages/template-edit.html.tmpl       |  11 ++
>   4 files changed, 268 insertions(+), 42 deletions(-)
>
> diff --git a/ui/css/kimchi.css b/ui/css/kimchi.css
> index 6cf2cc9..e0e05c7 100644
> --- a/ui/css/kimchi.css
> +++ b/ui/css/kimchi.css
> @@ -1597,7 +1597,15 @@ body.wok-gallery {
>   }
>
>   #template-edit-window .template-storage-cell.storage-pool {
> -  width: 220px !important;
> +  width: 180px !important;
> +}
> +
> +#template-edit-window .template-storage-cell.storage-path {
> +  width: 180px !important;
> +}
> +
> +#template-edit-window .template-storage-cell.source {
> +  width: 180px !important;
>   }
>
>   #template-edit-window .template-storage-cell.type {
> @@ -1609,7 +1617,7 @@ body.wok-gallery {
>   }
>
>   #template-edit-window .template-storage-cell.format {
> -  width: 320px;
> +  width: 250px;
>   }
>
>   #template-edit-window .template-interface-cell.network {
> diff --git a/ui/css/src/modules/_templates.scss b/ui/css/src/modules/_templates.scss
> index a75d803..2ae7412 100644
> --- a/ui/css/src/modules/_templates.scss
> +++ b/ui/css/src/modules/_templates.scss
> @@ -158,7 +158,13 @@ $kimchi-icon-path: '../images';
>           height: selectpicker height - 2px;
>       }
>       .template-storage-cell.storage-pool {
> -        width: 220px !important;
> +        width: 180px !important;
> +    }
> +    .template-storage-cell.storage-path {
> +        width: 180px !important;
> +    }
> +    .template-storage-cell.source {
> +        width: 180px !important;
>       }
>       .template-storage-cell.type {
>           width: 100px;
> @@ -167,7 +173,7 @@ $kimchi-icon-path: '../images';
>           width: 100px;
>       }
>       .template-storage-cell.format {
> -        width: 320px;
> +        width: 250px;
>       }
>       .template-interface-cell.network {
>           width: 220px;
> diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js
> index a2032cc..6b79fed 100644
> --- a/ui/js/src/kimchi.template_edit_main.js
> +++ b/ui/js/src/kimchi.template_edit_main.js
> @@ -226,6 +226,185 @@ kimchi.template_edit_main = function() {
>               });
>           };
>
> +        var initStorage_s390 = function(result) {
> +            // Gather storage 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) {
> +                if (storageData.storageSource == 'pool') {
> +                    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 = '';
> +                $.each(storagePoolsInfo, function(poolName, value) {
> +                    storageOptions += '<option value="' + poolName + '">' + poolName + '</option>';
> +                });
> +
> +
> +                $(storageRow + ' .selectStorageName').append(storageOptions);
> +                if (storageData.storageSource == 'pool') {
> +                    if (!$(storageRow + ' .selectStorageName option[value="' + storageData.storageName + '"]').length) {
> +                        var invalidOption = '<option disabled="disabled" selected="selected" value="' + storageData.storageName + '">' + storageData.storageName + '</option>';
> +                        $(storageRow + ' .selectStorageName').prepend(invalidOption);
> +                        $(storageRow + ' .selectStorageName').parent().addClass('has-error')
> +                    }
> +                    $(storageRow + ' .selectStorageName').val(storageData.storageName);
> +                    $(storageRow + ' span.storage-pool').show();
> +                    $(storageRow + ' span.storage-path').hide();
> +                } else {
> +                    $(storageRow + ' span.storage-pool').hide();
> +                    $(storageRow + ' span.storage-path').show();
> +                }
> +
> +                $(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 source
> +                $('#form-template-storage span.source').show();
> +                $(storageRow + ' #source').val(storageData.storageSource);
> +                $(storageRow + ' #source').on('change', function() {
> +                    var source = $(this).val();
> +                    $(storageRow + ' .template-storage-source').val(source);
> +                    if (source == 'path') {
> +                        $(storageRow + ' span.storage-pool').hide();
> +                        $(storageRow + ' span.storage-path').show();
> +                    } else {
> +                        $(storageRow + ' span.storage-pool').show();
> +                        $(storageRow + ' span.storage-path').hide();
> +                    }
> +                });
> +
> +                $(storageRow + ' #source').selectpicker();
> +
> +
> +
> +                // Set disk format
> +                if (isImageBasedTemplate()) {
> +                    $(storageRow + ' #diskFormat').val('qcow2');
> +                    $(storageRow + ' #diskFormat').prop('disabled', 'disabled');
> +                } else {
> +                    $(storageRow + ' #diskFormat').val(storageData.storageDiskFormat);
> +                    $(storageRow + ' #diskFormat').on('change', function() {
> +                        $(storageRow + ' .template-storage-disk-format').val($(this).val());
> +                    });
> +                }
> +                $(storageRow + ' #diskFormat').selectpicker();
> +
> +                $('.delete', '#form-template-storage').on("click", function(event) {
> +                    event.preventDefault();
> +                    $(this).parent().parent().remove();
> +                });
> +
> +                $(storageRow + ' select.selectStorageName').change(function() {
> +                    $(this).parent().parent().removeClass('has-error');
> +                    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();
> +                        }
> +                    } 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) {
> +                origDisks.sort(function(a, b) {
> +                    return a.index - b.index
> +                });
> +                $.each(origDisks, function(index, diskEntities) {
> +                    if (typeof diskEntities.pool !== 'undefined') {
> +                        var defaultPool = diskEntities.pool.name.split('/').pop()
> +                        var storageNodeData = {
> +                            storageSource: 'pool',
> +                            storageName: diskEntities.volume ? defaultPool + '/' + diskEntities.volume : defaultPool,
> +                            storageType: diskEntities.pool.type,
> +                            storageIndex: diskEntities.index,
> +                            storageDisk: diskEntities.size,
> +                            storageDiskFormat: diskEntities.format ? diskEntities.format : 'qcow2',
> +                            storageVolume: diskEntities.volume
> +                        }
> +                    } else {
> +                        var storageNodeData = {
> +                            storageSource: 'path',
> +                            storagePath: diskEntities.path,
> +                            storageType: 'dir',
> +                            storageIndex: diskEntities.index,
> +                            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 = {
> +                    storageSource: 'pool',
> +                    storageName: 'default',
> +                    storageType: 'dir',
> +                    storageDisk: '10',
> +                    storageDiskFormat: 'qcow2',
> +                    storageIndex: storageID
> +                }
> +                addStorageItem(storageNodeData);
> +            });
> +        };
> +
>           var initInterface = function(result) {
>               var networkItemNum = 0;
>               var addInterfaceItem = function(networkData) {
> @@ -340,49 +519,71 @@ kimchi.template_edit_main = function() {
>               });
>           }
>
> -        kimchi.listNetworks(initInterface);
> -        kimchi.listStoragePools(initStorage);
> +        if (kimchi.hostarch === s390xArch) {
> +            kimchi.listmacvtapNetworks(function(macvtapnet) {
> +                origmacvtapNetworks = macvtapnet;
> +                kimchi.listovsNetworks(function(ovsnet) {
> +                    origovsNetworks = ovsnet;
> +                    kimchi.listNetworks(initInterface_s390x);
> +                });
> +            });
> +
> +            kimchi.listStoragePools(initStorage_s390);
> +        } else {
> +            kimchi.listNetworks(initInterface);
> +            kimchi.listStoragePools(initStorage);
> +        }
> +
>           initProcessor();
>           checkInvalids();

> -    };
> -    kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate);
> -
> +        };
> +        kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate);
>       $('#tmpl-edit-button-save').on('click', function() {
> -        $button = $(this);
> -        $button.html('<span class="wok-loading-icon" /> ' + i18n['KCHAPI6010M']);
> -        $button.prop('disabled', true);
> -        $('.modal .wok-mask').removeClass('hidden');
> -        $('.modal input[type="text"]').prop('disabled', true);
> -        $('.modal input[type="checkbox"]').prop('disabled', true);
> -        $('.modal select').prop('disabled', true);
> -        $('.modal .selectpicker').addClass('disabled');
> -        var editableFields = ['name', 'memory', 'graphics', 'max-memory'];
> -        var data = {};
> -        var disks = $('.template-tab-body .item', '#form-template-storage');
> -        var disksForUpdate = new Array();
> -        $.each(disks, function(index, diskEntity) {
> -            var newDisk = {
> -                'index': index,
> -                'pool': { 'name': '/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()
> -            };
> -
> -            // image based template: add base to dictionary
> -            if ((baseImageTemplate) && (index == 0)) {
> -                newDisk["base"] = $('#template-edit-vmimage-textbox').val();
> -            }
> +                $button = $(this);
> +                $button.html('<span class="wok-loading-icon" /> ' + i18n['KCHAPI6010M']);
> +                $button.prop('disabled', true);
> +                $('.modal .wok-mask').removeClass('hidden');
> +                $('.modal input[type="text"]').prop('disabled', true);
> +                $('.modal input[type="checkbox"]').prop('disabled', true);
> +                $('.modal select').prop('disabled', true);
> +                $('.modal .selectpicker').addClass('disabled');
> +                var editableFields = ['name', 'memory', 'graphics', 'max-memory'];
> +                var data = {};
> +                var disks = $('.template-tab-body .item', '#form-template-storage');
> +                var disksForUpdate = new Array();
> +                $.each(disks, function(index, diskEntity) {
> +                    if (kimchi.hostarch == s390xArch && ($(diskEntity).find('.template-storage-source').val()) == 'path') {
> +                        var newDisk = {
> +                            'index': index,
> +                            'path': $(diskEntity).find('.template-storage-path').val(),
> +                            'size': Number($(diskEntity).find('.template-storage-disk').val()),
> +                            'format': $(diskEntity).find('.template-storage-disk-format').val()
> +                        };
> +                    } else {
> +                        var newDisk = {
> +                            'index': index,
> +                            'pool': {
> +                                'name': '/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()
> +                        };
> +

Why did you change the indentation level here?

>                      }
>
> -            var storageType = $(diskEntity).find('.template-storage-type').val();
> -            if (storageType === 'iscsi' || storageType === 'scsi') {
> -                newDisk['volume'] = newDisk['pool']['name'].split('/').pop();
> -                newDisk['pool']['name'] = newDisk['pool']['name'].slice(0, newDisk['pool']['name'].lastIndexOf('/'));
> -                delete newDisk.size;
> -            }
> -            disksForUpdate.push(newDisk);
> -        });
> -        data.disks = disksForUpdate;
> +                    // image based template: add base to dictionary
> +                    if ((baseImageTemplate) && (index == 0)) {
> +                        newDisk["base"] = $('#template-edit-vmimage-textbox').val();
> +                    }
>
> +                    var storageType = $(diskEntity).find('.template-storage-type').val();
> +                    if (storageType === 'iscsi' || storageType === 'scsi') {
> +                        newDisk['volume'] = newDisk['pool']['name'].split('/').pop();
> +                        newDisk['pool']['name'] = newDisk['pool']['name'].slice(0, newDisk['pool']['name'].lastIndexOf('/'));
> +                        delete newDisk.size;
> +                    }
> +                    disksForUpdate.push(newDisk);
> +                });
> +                data.disks = disksForUpdate;
>           $.each(editableFields, function(i, field) {
>               if (field == 'graphics') {
>                   var type = $('#form-template-general [name="' + field + '"]').val();
> diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
> index 6cac885..33533a1 100644
> --- a/ui/pages/template-edit.html.tmpl
> +++ b/ui/pages/template-edit.html.tmpl
> @@ -110,6 +110,7 @@
>                   <div role="tabpanel" class="tab-pane" id="storage">
>                       <form id="form-template-storage">
>                           <div class="template-tab-header">
> +                            <span class="template-storage-cell source" style="display:none">$_("Source")</span>
>                               <span class="template-storage-cell storage-pool">$_("Storage Pool")</span>
>                               <span class="template-storage-cell type">$_("Type")</span>
>                               <span class="template-storage-cell disk">$_("Disk(GB)")</span>
> @@ -182,10 +183,20 @@
>   </script>
>   <script id="template-storage-pool-tmpl" type="text/html">
>       <div id="storageRow{storageIndex}" class='item'>
> +      <span class="template-storage-cell source" style="display:none">
> +          <input class="template-storage-source" value={storageSource} type="text" style="display:none" />
> +          <select id="source">
> +             <option value="pool">pool</option>
> +             <option value="path">path</option>
> +          </select>
> +      </span>
>           <span class="template-storage-cell storage-pool">
>               <input class="template-storage-name" value="{storageName}" type="text" style="display:none" />
>               <select id="selectStorageName-{storageIndex}" class="selectStorageName"></select>
>           </span>
> +        <span class="template-storage-cell storage-path" style="display:none">
> +            <input class="template-storage-path storage-path form-control" value="{storagePath}" type="text" />
> +        </span>
>           <span class="template-storage-cell type">
>               <input class="template-storage-type form-control" value={storageType} readonly=true type="text" />
>           </span>




More information about the Kimchi-devel mailing list