Reviewed by: Archana Singh <archus@linux.vnet.ibm.com>
From: Rajat Gupta <rajgupta@linux.vnet.ibm.com> Introducing s390x UI Storage module for Edit Template under virtualization Signed-off-by: Rajat Gupta <rajgupta@linux.vnet.ibm.com> --- ui/css/kimchi.css | 12 +- ui/css/src/modules/_templates.scss | 10 +- ui/js/src/kimchi.template_edit_main.js | 214 +++++++++++++++++++++++++++++++-- ui/pages/template-edit.html.tmpl | 11 ++ 4 files changed, 235 insertions(+), 12 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..92ce977 100644 --- a/ui/js/src/kimchi.template_edit_main.js +++ b/ui/js/src/kimchi.template_edit_main.js @@ -226,6 +226,181 @@ 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,8 +515,20 @@ 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(); }; @@ -361,12 +548,23 @@ kimchi.template_edit_main = function() { 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() - }; + 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() + }; + } // image based template: add base to dictionary if ((baseImageTemplate) && (index == 0)) { diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl index 6cac885..432f986 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>