[Kimchi-devel] [PATCH V3] Edit Template redefined

Wen Wang wenwang at linux.vnet.ibm.com
Tue Nov 18 06:13:24 UTC 2014


Thanks Aline,

I will sent another version that reflect my two comments below.

On 11/18/2014 1:23 AM, Aline Manera wrote:
>
> On 11/17/2014 01:22 AM, Wen Wang wrote:
>> Thanks for the timely reply, just two inline comments:
>>
>> On 11/15/2014 1:57 AM, Aline Manera wrote:
>>>
>>> Some issues I found:
>>>
>>> 1. While trying to add a new network:
>>> |{
>>> ||   "reason":"KCHTMPL0017E: All networks for the template must be specified in a list.",
>>> ||   "code":"400 Bad Request",
>>> ||   "call_stack":"Traceback (most recent call last):\n  File \"/usr/lib/python2.7/site-packages/cherrypy||/_cprequest.py\",
>>> line 656, in respond\n    response.body = self.handler()\n  File \"/usr/lib/python2||.7/site-packages/cherrypy/lib/encoding.py\",
>>> line 188, in __call__\n    self.body = self.oldhandler(||*args, **kwargs)\n  File \"/usr/lib/python2.7/site-packages/cherrypy/_cpdispatch.py\",
>>> line 34, in __call__||\n    return self.callable(*self.args, **self.kwargs)\n  File \"/home/alinefm/kimchi/src/kimchi/control||/base.py\", line 162,
>>> in index\n    raise cherrypy.HTTPError(400, e.message)\nHTTPError: (400, u'KCHTMPL0017E||: All networks for the template must be specified in a list.')\n"
>>> ||}|
>> I cannot reproduce this I can successfully update the net work and 
>> here is my result of adding the network from Firebug:
>>
>
> I can reproduce it as many time as I want.
>
> The steps I did are:
>
> 1) Switch to "Network" tab on "Edit Template"
> 2) Select + icon to add new network
> 3) Select a network on combo box
> 4) Select the save icon (in the same network line along with edit icon)
> 4) Select "Save" button in the dialog footer
> 5) The PUT request will raise the above error.
>
I checked, and it's caused by adding the duplicated item in network. I 
will have this part changed and send another version
>> |{"storagepool":"/storagepools/ISO","name":"fedora20.1415180417383","cpus":1,"memory":1024,"disks":[{"index"||:0,"size":10}],"graphics":{"type":"vnc"},"networks":["1","dab","default","6","fsdfsdfs"]}|
>>
>> Could you please give me an access to one of your testing environment 
>> so that I can have a better loot at it?
>>
>>> 2. The "Save" button on footer must be shown only in the General Tab 
>>> as Storage and Network Tabs have different save handlers.
>>>
>> The template is a little bit different from the guest. What we are 
>> using for the api is to have all the data including network and the 
>> storage information submitted to the server. without clicking the 
>> "Save", network and the storage changes won't be updated. "Save" 
>> button will update information from all tabs to the server and share 
>> the same handler. I can change it to the one that only show in 
>> "General" but then we have to send a post of all the information of 
>> three tabs to the server every time we add or delete a network and 
>> storage. It is less efficient which I would not recommend.
>
> It is confusing for me have 2 save ways: one in a icon form and other 
> the Save button on footer.
> Is possible to remove the save icon so?
I think I can do that.
>
>>
>> Best Regards
>>
>> Wang Wen
>>>
>>> On 11/13/2014 04:47 AM, Wen Wang wrote:
>>>> From: Wen Wang<wenwang at linux.vnet.ibm.com>
>>>>
>>>> V2 -> V3:
>>>> Fix the bug that iscsi and scsi disk size won't change automatically
>>>>
>>>> V1 -> V2:
>>>>
>>>> 1) Enable "iSCSI" and "SCSI" for storage.
>>>> 2) Changed the storage tab from "storage" to "Storage".
>>>> 3) Fix the defect that when editing/adding "Storage" or "Interface" line
>>>> went down issue.
>>>> 4) "Storage" and "Interface" content can display properly on Remote and
>>>> Image created template.
>>>> 5) Fix the defect that "Image" didn't show properly when using a Image
>>>> created template.
>>>>
>>>> This patch redesigned "Edit Template" diaguage in "Templates". New "Edit
>>>> Template" will display all the related information into tabs of
>>>> "General", "Storage" and "Interface". Due to unfinished back-end work,
>>>> functions are not fully supported, which will be finished in the future
>>>> work.
>>>>
>>>> Temporary disabled functions:
>>>> 1) Multiple disk operation with multiple storage pools edit in template
>>>> for which reason the add button in "Storage" tab is disabled.
>>>> 2) iSCSI and SCSI storage pool add is removed since we are going to
>>>> allow this kind of operation in the process of creating a VM.
>>>>
>>>> Signed-off-by: Wen Wang<wenwang at linux.vnet.ibm.com>
>>>> ---
>>>>   ui/css/theme-default/template-edit.css |  116 +++++++----
>>>>   ui/js/src/kimchi.template_edit_main.js |  366 +++++++++++++++++++++++---------
>>>>   ui/pages/template-edit.html.tmpl       |  168 ++++++++-------
>>>>   3 files changed, 434 insertions(+), 216 deletions(-)
>>>>
>>>> diff --git a/ui/css/theme-default/template-edit.css b/ui/css/theme-default/template-edit.css
>>>> index 4975f1b..094e909 100644
>>>> --- a/ui/css/theme-default/template-edit.css
>>>> +++ b/ui/css/theme-default/template-edit.css
>>>> @@ -17,24 +17,33 @@
>>>>    */
>>>>   #template-edit-window {
>>>>       font-size: 13px;
>>>> -    height: 600px;
>>>> -    width: 1000px;
>>>> +    height: 500px;
>>>> +    width: 800px;
>>>>   }
>>>>
>>>> -.template-edit-fieldset {
>>>> -    float: left;
>>>> -    padding: 1em;
>>>> +#edit-template-tabs {
>>>> +    background: none repeat scroll 0 0 transparent;
>>>> +    border: medium none;
>>>> +    height: 100%;
>>>> +    padding: 0;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-label, .template-edit-wrapper-controls {
>>>> +#edit-template-tabs .form-template-inline-wrapper {
>>>> +    display: inline-block;
>>>>       vertical-align: top;
>>>> -    width: 470px;
>>>>   }
>>>>
>>>>   .template-edit-wrapper-label {
>>>> -    height: 18px;
>>>> -    line-height: 18px;
>>>> -    margin-top: 8px;
>>>> +    vertical-align: top;
>>>> +    min-width: 100px;
>>>> +    height: 35px;
>>>> +    line-height: 35px;
>>>> +    margin: 7px 0 8px;
>>>> +}
>>>> +
>>>> +.template-edit-wrapper-controls {
>>>> +    vertical-align: top;
>>>> +    width: 400px;
>>>>   }
>>>>
>>>>   .template-edit-wrapper-controls input[type="text"] {
>>>> @@ -56,7 +65,7 @@
>>>>
>>>>   .template-edit-wrapper-controls > .dropdown {
>>>>       margin: 5px 0 0 1px;
>>>> -    width: 440px;
>>>> +    width: 372px;
>>>>   }
>>>>
>>>>   .template-edit-wrapper-controls input[type="text"][disabled] {
>>>> @@ -65,41 +74,72 @@
>>>>       cursor: not-allowed;
>>>>   }
>>>>
>>>> -.hidden-area {
>>>> -    display: none;
>>>> +#edit-template-tabs .template-tab-header {
>>>> +    margin-bottom: 8px;
>>>> +    padding-bottom: 2px;
>>>> +    font-weight: bold;
>>>> +    border-bottom: 1px solid #999999;
>>>> +    overflow: hidden;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-controls .select-list-box {
>>>> -    width: 464px;
>>>> -    max-height: 168px;
>>>> -    overflow: auto;
>>>> -    margin-top: 5px;
>>>> -    border: 1px solid #ccc;
>>>> +#edit-template-tabs .template-tab-header .action-area {
>>>> +    float: right;
>>>> +    height: 20px;
>>>> +    width: 20px;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-controls .select-list-box>li>label {
>>>> -    display: block;
>>>> +#edit-template-tabs .template-interface-cell {
>>>> +    display: inline-block;
>>>> +    width: 250px;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-controls .select-list-box>li>label>
>>>> -input[type="checkbox"] {
>>>> -    display: none;
>>>> +#edit-template-tabs .template-storage-cell{
>>>> +    display: inline-block;
>>>> +    width: 230px;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .template-storage-cell label {
>>>> +    height: 25px;
>>>> +    padding: 2px;
>>>> +    border: 1px;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-controls .select-list-box>li>label>.item {
>>>> -    display: block;
>>>> -    height: 41px;
>>>> -    line-height: 41px;
>>>> -    padding: 0 20px 0 40px;
>>>> -    border-bottom: 1px solid #ccc;
>>>> -    box-shadow: 0px 1px 1px #fff;
>>>> -    text-shadow: -1px -1px 1px #ddd, 1px 1px 1px #fff;
>>>> -    color: #222;
>>>> -    font-size: 12px;
>>>> +#form-template-storage .template-tab-body select {
>>>> +    width: 140px;
>>>>   }
>>>>
>>>> -.template-edit-wrapper-controls .select-list-box>li>label>
>>>> -input[type="checkbox"]:CHECKED+.item {
>>>> -    background: #f8f8f8 url(../images/theme-default/check-green.png) no-repeat
>>>> -                10px center;
>>>> +#form-template-storage .template-tab-body input {
>>>> +    width: 56px;
>>>> +    height: 17px;
>>>>   }
>>>> +
>>>> +#form-template-storage .template-tab-body .template-storage-name {
>>>> +    width: 220px;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .template-tab-body input[readonly] {
>>>> +    background: none repeat scroll 0 0 rgba(0, 0, 0, 0);
>>>> +    border-color: transparent;
>>>> +    text-overflow: ellipsis;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .template-tab-body .item {
>>>> +    height: 25px;
>>>> +}
>>>> +
>>>> +#form-template-interface .template-tab-body select {
>>>> +    width: 180px;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .template-tab-body .action-area {
>>>> +    float: right;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .template-tab-body .action-area button {
>>>> +    width: 20px;
>>>> +    height: 20px;
>>>> +}
>>>> +
>>>> +#edit-template-tabs .hide {
>>>> +    display: none;
>>>> +}
>>>> \ No newline at end of file
>>>> diff --git a/ui/js/src/kimchi.template_edit_main.js b/ui/js/src/kimchi.template_edit_main.js
>>>> index 2f4cc9a..5073c62 100644
>>>> --- a/ui/js/src/kimchi.template_edit_main.js
>>>> +++ b/ui/js/src/kimchi.template_edit_main.js
>>>> @@ -16,19 +16,23 @@
>>>>    * limitations under the License.
>>>>    */
>>>>   kimchi.template_edit_main = function() {
>>>> -    var templateEditForm = $('#form-template-edit');
>>>> +    var templateEditMain = $('#edit-template-tabs');
>>>>       var origDisks;
>>>>       var origPool;
>>>> +    var origNetworks;
>>>>       var templateDiskSize;
>>>> -    $('#template-name', templateEditForm).val(kimchi.selectedTemplate);
>>>> -    kimchi.retrieveTemplate(kimchi.selectedTemplate, function(template) {
>>>> +    $('#template-name', templateEditMain).val(kimchi.selectedTemplate);
>>>> +    templateEditMain.tabs();
>>>> +
>>>> +    var initTemplate = function(template) {
>>>>           origDisks =  template.disks;
>>>>           origPool = template.storagepool;
>>>> +        origNetworks = template.networks;
>>>>           for(var i=0;i<template.disks.length;i++){
>>>>               if(template.disks[i].base){
>>>>                   template["vm-image"] = template.disks[i].base;
>>>> -                $('#templ-edit-cdrom').addClass('hide-content');
>>>> -                $('#templ-edit-vm-image').removeClass('hide-content');
>>>> +                $('.templ-edit-cdrom').addClass('hide');
>>>> +                $('.templ-edit-vm-image').removeClass('hide');
>>>>                   break;
>>>>               }
>>>>           }
>>>> @@ -37,18 +41,12 @@ kimchi.template_edit_main = function() {
>>>>               if (prop == 'graphics') {
>>>>                  value = value["type"];
>>>>               }
>>>> -            $('input[name="' + prop + '"]', templateEditForm).val(value);
>>>> -        }
>>>> -        var disks = template.disks;
>>>> -        $('input[name="disks"]').val(disks[0].size);
>>>> -        templateDiskSize = $('input[name="disks"]').val();
>>>> -        if (disks[0].volume) {
>>>> -            var spool_value = $('#form-template-edit [name="storagepool"]').val();
>>>> -            $('input[name="storagepool"]', templateEditForm).val(spool_value + '/' + disks[0].volume);
>>>> -            $('input[name="disks"]', templateEditForm).attr('disabled','disabled');
>>>> +            $('input[name="' + prop + '"]', templateEditMain).val(value);
>>>>           }
>>>>
>>>>           var vncOpt = [{label: 'VNC', value: 'vnc'}];
>>>> +        $('#template-edit-graphics').append('<option selected>VNC</option>');
>>>> +        $('#template-edit-graphics').append('<option>Spice</option>');
>>>>           kimchi.select('template-edit-graphics-list', vncOpt);
>>>>           var enableSpice = function() {
>>>>               if (kimchi.capabilities == undefined) {
>>>> @@ -61,119 +59,283 @@ kimchi.template_edit_main = function() {
>>>>               }
>>>>           };
>>>>           enableSpice();
>>>> -
>>>> -        var scsipools = {};
>>>> -        kimchi.listStoragePools(function(result) {
>>>> -            var options = [];
>>>> -            if (result && result.length) {
>>>> -                $.each(result, function(index, storagePool) {
>>>> -                    if ((storagePool.state=="active") && (storagePool.type !== 'kimchi-iso')) {
>>>> -                        if ((storagePool.type == 'iscsi') || (storagePool.type == 'scsi')){
>>>> -                            scsipools[storagePool.name] = [];
>>>> -                            kimchi.listStorageVolumes(storagePool.name, function(result) {
>>>> -                                if (result && result.length) {
>>>> -                                    $.each(result, function(index, storageVolume) {
>>>> -                                        options.push({
>>>> -                                            label: storagePool.name + '/' + storageVolume.name,
>>>> -                                            value: '/storagepools/' + storagePool.name + '/' + storageVolume.name
>>>> -                                        });
>>>> -                                        scsipools[storagePool.name].push(storageVolume)
>>>> -                                    });
>>>> -                                }
>>>> -                                kimchi.select('template-edit-storagePool-list', options);
>>>> -                            });
>>>> -                        }
>>>> -                        else {
>>>> -                            options.push({
>>>> -                                label: storagePool.name,
>>>> -                                value: '/storagepools/' + storagePool.name
>>>> -                            });
>>>> -                        }
>>>> +        var initStorage = function(result) {
>>>> +            var scsipools = {};
>>>> +            var addStorageItem = function(storageData) {
>>>> +                var thisName;
>>>> +                var thisType;
>>>> +                var thisDisk;
>>>> +                var nodeStorage = $.parseHTML(kimchi.substitute($('#template-storage-pool-tmpl').html(), storageData));
>>>> +                $('.template-tab-body', '#form-template-storage').append(nodeStorage);
>>>> +                $('.edit', '#form-template-storage').button({
>>>> +                    icons : {primary : 'ui-icon-pencil'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    var storageItem = $(this).parent().parent();
>>>> +                    thisName = $('.template-storage-name', storageItem).val();
>>>> +                    thisType = $('.template-storage-type', storageItem).val();
>>>> +                    thisDisk = $('.template-storage-disk', storageItem).val();
>>>> +                    $('.template-storage-name', storageItem).hide();
>>>> +                    $('.template-storage-disk', storageItem).attr('readonly', false);
>>>> +                    if (thisType === 'iscsi' || thisType === 'scsi') {
>>>> +                        $('.template-storage-disk', storageItem).attr('readonly', true);
>>>> +                    } else {
>>>> +                        $('.template-storage-disk', storageItem).attr('readonly', false);
>>>>                       }
>>>> +                    $('.save', storageItem).parent().show();
>>>> +                    $('.delete', storageItem).parent().hide();
>>>> +                    var selectedStorage = $('select', storageItem).val();
>>>> +                    $('.template-storage-name', storageItem).val(selectedStorage).hide();
>>>> +                    $('select', storageItem).val(thisName).show();
>>>>                   });
>>>> -            }
>>>> -            if ($.isEmptyObject(scsipools)) {
>>>> -                kimchi.select('template-edit-storagePool-list', options);
>>>> -            }
>>>> -        });
>>>> -        kimchi.listNetworks(function(result) {
>>>> -            if(result && result.length > 0) {
>>>> -                var html = '';
>>>> -                var tmpl = $('#tmpl-network').html();
>>>> -                $.each(result, function(index, network) {
>>>> -                    if (result[index].state === 'active')
>>>> -                        html += kimchi.substitute(tmpl, network);
>>>> +                $('.delete', '#form-template-storage').button({
>>>> +                    icons : {primary : 'ui-icon-trash'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    $(this).parent().parent().remove();
>>>> +                });
>>>> +                $('.cancel', '#form-template-storage').button({
>>>> +                    icons : {primary : 'ui-icon-arrowreturnthick-1-w'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    var cancelEntity = $(this).parent().parent();
>>>> +                    if ($('.template-storage-name', cancelEntity).val() === 'null') {
>>>> +                        cancelEntity.remove();
>>>> +                    } else {
>>>> +                        $('select', cancelEntity).hide();
>>>> +                        $('.template-storage-name', cancelEntity).val(thisName).attr('readonly', true).show();
>>>> +                        $('.template-storage-type', cancelEntity).val(thisType).attr('readonly', true);
>>>> +                        $('.template-storage-disk', cancelEntity).val(thisDisk).attr('readonly', true);
>>>> +                        $('.save', cancelEntity).parent().hide();
>>>> +                        $('.edit', cancelEntity).parent().show();
>>>> +                    }
>>>> +                });
>>>> +                $('.save', '#form-template-storage').button({
>>>> +                    icons : {primary : 'ui-icon-disk'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    var storageItem = $(this).parent().parent();
>>>> +                    $('.save', storageItem).parent().hide();
>>>> +                    $('.delete', storageItem).parent().show();
>>>> +                    var selectedStorage = $('select', storageItem).val();
>>>> +                    $('.template-storage-name', storageItem).val(selectedStorage).attr('readonly', true).show();
>>>> +                    $('.template-storage-disk', storageItem).attr('readonly', true);
>>>> +                    $('.template-storage-type', storageItem).attr('readonly', true);
>>>> +                    $('select', storageItem).hide();
>>>>                   });
>>>> -                $('#template-edit-network-list').html(html).show();
>>>> -                if(template.networks && template.networks.length > 0) {
>>>> -                    $('input[name="networks"]', templateEditForm).each(function(index, element) {
>>>> -                        var value = $(element).val();
>>>> -                        if(template.networks.indexOf(value) >= 0) {
>>>> -                            $(element).prop('checked', true);
>>>> +                var storageOptions = '';
>>>> +                var scsiOptions = '';
>>>> +                $('select', '#form-template-storage').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) {
>>>> +                                    scsiOptions += '<option>' + storageEntities.name + '/' + scsiEntities.name + '</option>';
>>>> +                                });
>>>> +                                $('select', '#form-template-storage').append(scsiOptions);
>>>> +                            }, function() {});
>>>> +                        } else {
>>>> +                            var isSlected = storageEntities.name === 'default' ? ' selected' : '';
>>>> +                            storageOptions += '<option' + isSlected + '>' + storageEntities.name + '</option>';
>>>> +                        }
>>>> +                    }
>>>> +                });
>>>> +                $('select', '#form-template-storage').append(storageOptions);
>>>> +                $('select', '#form-template-storage').change(function() {
>>>> +                    var selectedItem = $(this).parent().parent();
>>>> +                    var tempStorageName = $(this).val();
>>>> +                    var tempType;
>>>> +                    tempStorageName =tempStorageName.split('/')[0];
>>>> +                    var scsiCap;
>>>> +                    $.each(result, function(index, storageEntities) {
>>>> +                        if (tempStorageName === storageEntities.name) {
>>>> +                            selectedItem.find('.template-storage-type').val(storageEntities.type);
>>>> +                            scsiCap = storageEntities.capacity / Math.pow(1024, 3);
>>>> +                            tempType = storageEntities.type;
>>>>                           }
>>>>                       });
>>>> +                    if (tempType === 'iscsi' || tempType === 'scsi') {
>>>> +                        $('.template-storage-disk', selectedItem).attr('readonly', true).val(scsiCap);
>>>> +                    } else {
>>>> +                        $('.template-storage-disk', selectedItem).attr('readonly', false).val('10');
>>>> +                    }
>>>> +                });
>>>> +            };
>>>> +
>>>> +            if ((origDisks && origDisks.length) && (origPool && origPool.length)) {
>>>> +                splitPool = origPool.split('/');
>>>> +                var defaultPool;
>>>> +                var defaultType;
>>>> +                $.each(result, function(index, poolEntities) {
>>>> +                    if (poolEntities.name === splitPool[splitPool.length-1]) {
>>>> +                        defaultType = poolEntities.type;
>>>> +                        defaultPool = splitPool[splitPool.length-1]
>>>> +                    }
>>>> +                });
>>>> +                if (origDisks[0]['volume']) {
>>>> +                    defaultPool = defaultPool + '/' + origDisks[0]['volume'];
>>>>                   }
>>>> -            } else {
>>>> -                $('#template-edit-network-list').hide();
>>>> +                $.each(origDisks, function(index, diskEntities) {
>>>> +                    var storageNodeData = {
>>>> +                        viewMode : '',
>>>> +                        editMode : 'hide',
>>>> +                        storageName : defaultPool,
>>>> +                        storageType : defaultType,
>>>> +                        storageDisk : diskEntities.size
>>>> +                    }
>>>> +                    addStorageItem(storageNodeData);
>>>> +                });
>>>> +                $('.template-storage-disk').attr('readonly', true);
>>>>               }
>>>> -        });
>>>> -    });
>>>>
>>>> -    $('#template-edit-storagePool').change(function() {
>>>> -        storagepool = $(this).val();
>>>> -        var storageArray = storagepool.split("/");
>>>> -        if (storageArray.length > 3) {
>>>> -            volumeName = storageArray.pop();
>>>> -            poolName = storageArray.pop();
>>>> -            kimchi.getStoragePoolVolume(poolName, volumeName, function(result) {
>>>> -                $('input[name="disks"]', templateEditForm).val(result.capacity / Math.pow(1024,3));
>>>> -                $('input[name="disks"]', templateEditForm).attr('disabled','disabled');
>>>> -                return false;
>>>> -            }, function (err) {
>>>> -                kimchi.message.error(err.responseJSON.reason);
>>>> +            $('#template-edit-storage-add-button').button({
>>>> +                icons: {
>>>> +                    primary: "ui-icon-plusthick"
>>>> +                },
>>>> +                text: false,
>>>> +                disabled: true
>>>> +            }).click(function(event) {
>>>> +                event.preventDefault();
>>>> +                var storageNodeData = {
>>>> +                    viewMode : 'hide',
>>>> +                    editMode : '',
>>>> +                    storageName : 'null',
>>>> +                    storageType : 'dir',
>>>> +                    storageDisk : '10'
>>>> +                }
>>>> +                addStorageItem(storageNodeData);
>>>>               });
>>>> -        } else {
>>>> -            $('input[name="disks"]', templateEditForm).removeAttr('disabled');
>>>> -            $('input[name="disks"]', templateEditForm).val(templateDiskSize);
>>>> -        }
>>>> -    });
>>>> -    $('input[name="disks"]', templateEditForm).keyup(function() {
>>>> -        templateDiskSize = $('input[name="disks"]', templateEditForm).val();
>>>> -    });
>>>> +        };
>>>> +        var initInterface = function(result) {
>>>> +            var addInterfaceItem = function(networkData) {
>>>> +                var nodeInterface = $.parseHTML(kimchi.substitute($('#template-interface-tmpl').html(), networkData));
>>>> +                $('.template-tab-body', '#form-template-interface').append(nodeInterface);
>>>> +                $('.edit', '#form-template-interface').button({
>>>> +                    icons : {primary : 'ui-icon-pencil'},
>>>> +                    text : false,
>>>> +                    disabled : true
>>>> +                });
>>>> +                $('.delete', '#form-template-interface').button({
>>>> +                    icons : {primary : 'ui-icon-trash'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    $(this).parent().parent().remove();
>>>> +                });
>>>> +                $('.cancel', '#form-template-interface').button({
>>>> +                    icons : {primary : 'ui-icon-arrowreturnthick-1-w'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    $(this).parent().parent().remove();
>>>> +                });
>>>> +                $('.save', '#form-template-interface').button({
>>>> +                    icons : {primary : 'ui-icon-disk'},
>>>> +                    text : false
>>>> +                }).click(function(evt) {
>>>> +                    evt.preventDefault();
>>>> +                    var interItem = $(this).parent().parent();
>>>> +                    $('.save', interItem).parent().hide();
>>>> +                    $('.delete', interItem).parent().show();
>>>> +                    var selectedInterface = $('select', interItem).val();
>>>> +                    $('.template-interface-name', interItem).val(selectedInterface).show();
>>>> +                    $('select', interItem).hide();
>>>> +                });
>>>> +                var networkOptions = '';
>>>> +                for(var i=0;i<result.length;i++){
>>>> +                    if(result[i].state === "active") {
>>>> +                        var isSlected = i==0 ? ' selected' : '';
>>>> +                        networkOptions += '<option' + isSlected + '>' + result[i].name + '</option>';
>>>> +                    }
>>>> +                }
>>>> +                $('select', '#form-template-interface').find('option').remove();
>>>> +                $('select', '#form-template-interface').append(networkOptions);
>>>> +            };
>>>> +            if(result && result.length > 0) {
>>>> +                $.each(result, function(index, data) {
>>>> +                    if($.inArray(data.name, origNetworks) > -1) {
>>>> +                        addInterfaceItem({
>>>> +                            mac : '',
>>>> +                            network : data.name,
>>>> +                            type : 'network',
>>>> +                            viewMode : '',
>>>> +                            editMode : 'hide'
>>>> +                        });
>>>> +                    }
>>>> +                });
>>>> +            }
>>>> +            $('#template-edit-interface-add-button').button({
>>>> +                icons: {
>>>> +                    primary: 'ui-icon-plusthick'
>>>> +                },
>>>> +                text: false
>>>> +            }).click(function(evt) {
>>>> +                evt.preventDefault();
>>>> +                addInterfaceItem({
>>>> +                    mac : '',
>>>> +                    network : '',
>>>> +                    type : 'network',
>>>> +                    viewMode : 'hide',
>>>> +                    editMode : ''
>>>> +                });
>>>> +            });
>>>> +        };
>>>> +        kimchi.listNetworks(initInterface);
>>>> +        kimchi.listStoragePools(initStorage);
>>>> +    };
>>>> +    kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate);
>>>> +
>>>>
>>>>       $('#tmpl-edit-button-save').on('click', function() {
>>>> -        var editableFields = [ 'name', 'cpus', 'memory', 'storagepool', 'disks', 'graphics'];
>>>> +        var editableFields = [ 'name', 'cpus', 'memory', 'disks', '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();
>>>> +        tempName = tempName.split('/');
>>>> +        var tempNameHead =tempName[0];
>>>> +        var tempNameTail = tempNameHead;
>>>> +        if(tempNameHead === 'iscsi' || tempNameHead =='scsi') {
>>>> +            tempNameTail = tempName[tempName.length-1];
>>>> +        }
>>>> +        tempName = '/storagepools/' + tempNameHead;
>>>> +        data['storagepool'] = tempName;
>>>>           $.each(editableFields, function(i, field) {
>>>>               /* Support only 1 disk at this moment */
>>>>               if (field == 'disks') {
>>>> -               origDisks[0].size = Number($('#form-template-edit [name="' + field + '"]').val());
>>>> +                var tmpItem = $('#form-template-storage .item');
>>>> +                origDisks[0].size = Number($('.template-storage-disk', tmpItem).val());
>>>> +                if($('.template-storage-type', tmpItem).val() === 'iscsi' || $('.template-storage-type', tmpItem).val() =='scsi') {
>>>> +                    origDisks[0]['volume'] = tempNameTail;
>>>> +                } else {
>>>> +                    origDisks[0]['volume'] && delete origDisks[0]['volume'];
>>>> +                }
>>>>                  data[field] = origDisks;
>>>>               }
>>>>               else if (field == 'graphics') {
>>>> -               var type = $('#form-template-edit [name="' + field + '"]').val();
>>>> +               var type = $('#form-template-general [name="' + field + '"]').val();
>>>>                  data[field] = {'type': type};
>>>>               }
>>>>               else {
>>>> -               data[field] = $('#form-template-edit [name="' + field + '"]').val();
>>>> +               data[field] = $('#form-template-general [name="' + field + '"]').val();
>>>>               }
>>>>           });
>>>>           data['memory'] = Number(data['memory']);
>>>>           data['cpus']   = Number(data['cpus']);
>>>> -        storagepool = data['storagepool'];
>>>> -        storageArray = storagepool.split("/");
>>>> -        if (storageArray.length > 3){
>>>> -            /* Support only 1 disk at this moment */
>>>> -            data["disks"][0].volume = storageArray.pop();
>>>> -            data['storagepool'] = storageArray.join("/");
>>>> -        } else if (data["disks"][0].volume) {
>>>> -            delete data["disks"][0].volume;
>>>> -        }
>>>> -        var networks = templateEditForm.serializeObject().networks;
>>>> -        if (networks instanceof Array) {
>>>> -            data.networks = networks;
>>>> -        } else if (networks != null) {
>>>> -            data.networks = [networks];
>>>> +        var networks = $('.template-tab-body .item', '#form-template-interface');
>>>> +        var networkForUpdate = new Array();
>>>> +        $.each(networks, function(index, networkEntities) {
>>>> +            networkForUpdate.push($('.template-interface-name', networkEntities).val());
>>>> +        });
>>>> +        if (networkForUpdate instanceof Array) {
>>>> +            data.networks = networkForUpdate;
>>>> +        } else if (networkForUpdate != null) {
>>>> +            data.networks = [networkForUpdate];
>>>>           } else {
>>>>               data.networks = [];
>>>>           }
>>>> diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
>>>> index 5a71d91..018ac10 100644
>>>> --- a/ui/pages/template-edit.html.tmpl
>>>> +++ b/ui/pages/template-edit.html.tmpl
>>>> @@ -28,74 +28,67 @@
>>>>           <div class="close">X</div>
>>>>       </header>
>>>>       <div class="content">
>>>> -        <form id="form-template-edit">
>>>> +        <div id="edit-template-tabs">
>>>>               <input type="hidden" id="template-name" name="templateName" />
>>>> -            <fieldset class="template-edit-fieldset">
>>>> -                <div>
>>>> +            <ul>
>>>> +                <li>
>>>> +                    <a href="#form-template-general">$_("General")</a>
>>>> +                </li>
>>>> +                <li>
>>>> +                    <a href="#form-template-storage">$_("Storage")</a>
>>>> +                </li>
>>>> +                <li>
>>>> +                    <a href="#form-template-interface">$_("Interface")</a>
>>>> +                </li>
>>>> +            </ul>
>>>> +            <form id="form-template-general">
>>>> +                <div class="form-template-inline-wrapper">
>>>>                       <div class="template-edit-wrapper-label">
>>>>                           <label for="template-edit-id-textbox">$_("Name")</label>
>>>>                       </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-id-textbox" name="name" type="text" />
>>>> -                    </div>
>>>> -                </div>
>>>> -                <div>
>>>>                       <div class="template-edit-wrapper-label">
>>>>                           <label for="template-edit-vendor-textbox">$_("Vendor")</label>
>>>>                       </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" />
>>>> -                    </div>
>>>> -                </div>
>>>> -                <div>
>>>>                       <div class="template-edit-wrapper-label">
>>>>                           <label for="template-edit-version-textbox">$_("Version")</label>
>>>>                       </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" />
>>>> -                    </div>
>>>> -                </div>
>>>> -                <div>
>>>>                       <div class="template-edit-wrapper-label">
>>>>                           <label for="template-edit-cpu-textbox">$_("CPU Number")</label>
>>>>                       </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-cpu-textbox" name="cpus" type="text" />
>>>> -                    </div>
>>>> -                </div>
>>>> -                <div>
>>>>                       <div class="template-edit-wrapper-label">
>>>>                           <label for="template-edit-memory-textbox">$_("Memory (MB)")</label>
>>>>                       </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-memory-textbox" name="memory" type="text" />
>>>> +                    <div class="template-edit-wrapper-label templ-edit-cdrom">
>>>> +                        <label for="template-edit-cdrom-textbox">$_("CDROM")</label>
>>>> +                    </div>
>>>> +                    <div class="template-edit-wrapper-label templ-edit-vm-image hide">
>>>> +                        <label for="template-edit-vmimage-textbox">$_("Image File")</label>
>>>>                       </div>
>>>> -                </div>
>>>> -                <div>
>>>>                       <div class="template-edit-wrapper-label">
>>>> -                        <label for="template-edit-disk-textbox">$_("Disk (GB)")</label>
>>>> +                        <label>$_("Graphics")</label>
>>>>                       </div>
>>>> +                </div>
>>>> +                <div class="form-template-inline-wrapper">
>>>>                       <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-disk-textbox" name="disks" type="text" />
>>>> +                        <input id="template-edit-id-textbox" name="name" type="text" />
>>>>                       </div>
>>>> -                </div>
>>>> -            </fieldset>
>>>> -            <fieldset class="template-edit-fieldset">
>>>> -                <div id="templ-edit-cdrom">
>>>> -                    <div class="template-edit-wrapper-label">
>>>> -                        <label for="template-edit-cdrom-textbox">$_("CDROM")</label>
>>>> +                    <div class="template-edit-wrapper-controls">
>>>> +                        <input id="template-edit-vendor-textbox" name="os_distro" type="text" disabled="disabled" />
>>>>                       </div>
>>>>                       <div class="template-edit-wrapper-controls">
>>>> -                        <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled"/>
>>>> +                        <input id="template-edit-version-textbox" name="os_version" type="text" disabled="disabled" />
>>>>                       </div>
>>>> -                </div>
>>>> -                <div id="templ-edit-vm-image" class="hide-content">
>>>> -                    <div class="template-edit-wrapper-label">$_("Image File")</div>
>>>> -                    <div class="template-edit-wrapper-controls"><input name="vm-image" type="text" disabled/></div>
>>>> -                </div>
>>>> -                <div>
>>>> -                    <div class="template-edit-wrapper-label">
>>>> -                        <label>$_("Graphics")</label>
>>>> +                    <div class="template-edit-wrapper-controls">
>>>> +                        <input id="template-edit-cpu-textbox" name="cpus" type="text" />
>>>> +                    </div>
>>>> +                    <div class="template-edit-wrapper-controls">
>>>> +                        <input id="template-edit-memory-textbox" name="memory" type="text" />
>>>> +                    </div>
>>>> +                    <div class="template-edit-wrapper-controls templ-edit-cdrom">
>>>> +                        <input id="template-edit-cdrom-textbox" name="cdrom" type="text" disabled="disabled" />
>>>> +                    </div>
>>>> +                    <div class="template-edit-wrapper-controls templ-edit-vm-image hide">
>>>> +                        <input id="template-edit-vmimage-textbox" name="vm-image" type="text" disabled="disabled" />
>>>>                       </div>
>>>>                       <div class="template-edit-wrapper-controls">
>>>>                           <div class="btn dropdown popable">
>>>> @@ -108,40 +101,26 @@
>>>>                           </div>
>>>>                       </div>
>>>>                   </div>
>>>> -                <div>
>>>> -                    <div class="template-edit-wrapper-label">
>>>> -                        <label>$_("Storage Pool")</label>
>>>> -                    </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <div class="btn dropdown popable">
>>>> -                            <input id="template-edit-storagePool" name="storagepool" type="hidden" />
>>>> -                            <span class="text" id="template-edit-storage-label"></span><span class="arrow"></span>
>>>> -                            <div class="popover" style="width: 100%">
>>>> -                                <ul class="select-list" id="template-edit-storagePool-list" data-target="template-edit-storagePool" data-label="template-edit-storage-label">
>>>> -                                </ul>
>>>> -                            </div>
>>>> -                        </div>
>>>> -                    </div>
>>>> +            </form>
>>>> +            <form id="form-template-storage">
>>>> +                <div class="template-tab-header">
>>>> +                    <span class="template-storage-cell">$_("Storage Pool")</span>
>>>> +                    <span class="template-storage-cell">$_("Type")</span>
>>>> +                    <span class="template-storage-cell">$_("Disk(GB)")</span>
>>>> +                    <button type="button" id="template-edit-storage-add-button" class="action-area"></button>
>>>>                   </div>
>>>> -                <div>
>>>> -                    <div class="template-edit-wrapper-label">
>>>> -                        <label>$_("Network")</label>
>>>> -                    </div>
>>>> -                    <div class="template-edit-wrapper-controls">
>>>> -                        <ul class="select-list-box" id="template-edit-network-list">
>>>> -                        </ul>
>>>> -                        <script id="tmpl-network" type="text/html">
>>>> -                            <li>
>>>> -                                <label>
>>>> -                                    <input name="networks" type="checkbox" value="{name}" />
>>>> -                                    <span class="item">{name}</span>
>>>> -                                </label>
>>>> -                            </li>
>>>> -                        </script>
>>>> -                    </div>
>>>> +                <div class="template-tab-body">
>>>>                   </div>
>>>> -            </fieldset>
>>>> -        </form>
>>>> +            </form>
>>>> +            <form id="form-template-interface">
>>>> +                <div class="template-tab-header">
>>>> +                    <span class="template-interface-cell">$_("Network")</span>
>>>> +                    <span class="template-interface-cell">$_("Type")</span>
>>>> +                    <button type="button" id="template-edit-interface-add-button" class="action-area"></button>
>>>> +                </div>
>>>> +                <div class="template-tab-body"></div>
>>>> +            </form>
>>>> +        </div>
>>>>       </div>
>>>>       <footer>
>>>>           <div class="btn-group">
>>>> @@ -152,3 +131,40 @@
>>>>   <script>
>>>>       kimchi.template_edit_main();
>>>>   </script>
>>>> +<script id="template-storage-pool-tmpl" type="text/html">
>>>> +    <div class='item'>
>>>> +        <span class="template-storage-cell">
>>>> +            <input class="template-storage-name {viewMode}" value={storageName} readonly=true type="text"/>
>>>> +            <select class="{editMode}"></select>
>>>> +        </span>
>>>> +        <span class="template-storage-cell">
>>>> +            <input class="template-storage-type" value={storageType} readonly=true type="text" />
>>>> +        </span>
>>>> +        <span class="template-storage-cell">
>>>> +            <input class="template-storage-disk" value={storageDisk} type="text" />
>>>> +        </span>
>>>> +        <span class="action-area {editMode}">
>>>> +            <button class="save"></button><button class="cancel"></button>
>>>> +        </span>
>>>> +        <span class="action-area {viewMode}">
>>>> +            <button class="edit"></button><button class="delete"></button>
>>>> +        </span>
>>>> +    </div>
>>>> +</script>
>>>> +<script id="template-interface-tmpl" type="text/html">
>>>> +    <div class="item">
>>>> +        <span class="template-interface-cell">
>>>> +            <input class="template-interface-name {viewMode}" readonly="true" type="text"  value={network} />
>>>> +            <select class="{editMode}"></select>
>>>> +        </span>
>>>> +        <span class="template-interface-cell">
>>>> +            <input value={type} readonly=true type="text" />
>>>> +        </span>
>>>> +        <span class="action-area {editMode}">
>>>> +            <button class="save"></button><button class="cancel"></button>
>>>> +        </span>
>>>> +        <span class="action-area {viewMode}">
>>>> +            <button class="edit"></button><button class="delete"></button>
>>>> +        </span>
>>>> +    </div>
>>>> +</script>
>>>> \ No newline at end of file
>>>
>>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ovirt.org/pipermail/kimchi-devel/attachments/20141118/deecdb81/attachment.html>


More information about the Kimchi-devel mailing list