Hello,
Following patch is still having merge conflict while trying to apply to
the next branch,
Hence I will be sending V4 patch.
Thanks and Regards,
Rajat Gupta
On 9/15/2016 8:34 AM, archus(a)linux.vnet.ibm.com wrote:
From: Rajat Gupta <rajgupta(a)linux.vnet.ibm.com>
Introducing s390x UI Interfaces module for Edit Template under virtualization
Signed-off-by: Rajat Gupta <rajgupta(a)linux.vnet.ibm.com>
---
ui/js/src/kimchi.api.js | 44 ++++++
ui/js/src/kimchi.main.js | 5 +
ui/js/src/kimchi.template_edit_main.js | 257 +++++++++++++++++++++++++++++++--
ui/pages/template-edit.html.tmpl | 29 ++++
4 files changed, 319 insertions(+), 16 deletions(-)
diff --git a/ui/js/src/kimchi.api.js b/ui/js/src/kimchi.api.js
index 2f127aa..950ca00 100644
--- a/ui/js/src/kimchi.api.js
+++ b/ui/js/src/kimchi.api.js
@@ -596,6 +596,34 @@ var kimchi = {
});
},
+ listmacvtapNetworks: function(suc, err) {
+ wok.requestJSON({
+ url: 'plugins/kimchi/interfaces?type=^nic|bonding|vlan$',
+ type: 'GET',
+ contentType: 'application/json',
+ dataType: 'json',
+ resend: true,
+ success: suc,
+ error: err ? err : function(data) {
+ wok.message.error(data.responseJSON.reason);
+ }
+ });
+ },
+
+ listovsNetworks: function(suc, err) {
+ wok.requestJSON({
+ url: 'plugins/kimchi/ovsbridges',
+ type: 'GET',
+ contentType: 'application/json',
+ dataType: 'json',
+ resend: true,
+ success: suc,
+ error: err ? err : function(data) {
+ wok.message.error(data.responseJSON.reason);
+ }
+ });
+ },
+
toggleNetwork : function(name, on, suc, err) {
var action = on ? "activate" : "deactivate";
wok.requestJSON({
@@ -1271,3 +1299,19 @@ var kimchi = {
});
}
};
+
+ /**
+ * Get the host information.
+ */
+
+ kimchi.getHostDetails = function(suc, err) {
+ wok.requestJSON({
+ url: 'plugins/gingerbase/host',
+ type: 'GET',
+ resend: true,
+ contentType: 'application/json',
+ dataType: 'json',
+ success: suc,
+ error: err
+ });
+ }
diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js
index b6de2cf..f3078ec 100644
--- a/ui/js/src/kimchi.main.js
+++ b/ui/js/src/kimchi.main.js
@@ -33,6 +33,11 @@ kimchi.getCapabilities(function(result) {
kimchi.capabilities = {};
});
+kimchi.hostarch = undefined;
+kimchi.getHostDetails(function(result) {
+ kimchi.hostarch = result["architecture"];
+});
+
$(function(){
$('body').removeClass('wok-list wok-gallery');
});
diff --git a/ui/js/src/kimchi.template_edit_main.js
b/ui/js/src/kimchi.template_edit_main.js
index a2032cc..9ccf9cc 100644
--- a/ui/js/src/kimchi.template_edit_main.js
+++ b/ui/js/src/kimchi.template_edit_main.js
@@ -19,8 +19,13 @@ kimchi.template_edit_main = function() {
var templateEditMain = $('#edit-template-tabs');
var origDisks;
var origNetworks;
+ var origInterfaces;
+ var origmacvtapNetworks;
+ var origovsNetworks;
var templateDiskSize;
var baseImageTemplate;
+ var s390xArch = 's390x';
+
$('#template-name', templateEditMain).val(kimchi.selectedTemplate);
$('#edit-template-tabs
a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
$('.tab-content').css('overflow', 'hidden');
@@ -47,6 +52,7 @@ kimchi.template_edit_main = function() {
var initTemplate = function(template) {
origDisks = template.disks;
origNetworks = template.networks;
+ origInterfaces = template.interfaces;
for (var i = 0; i < template.disks.length; i++) {
if (template.disks[i].base) {
template["vm-image"] = template.disks[i].base;
@@ -268,10 +274,170 @@ kimchi.template_edit_main = function() {
});
};
- var initProcessor = function() {
- var setCPUValue = function() {
- if (!$('#cores').hasClass("invalid-field") &&
$('#cores').val() != "") {
- var computedCpu = parseInt($("#cores").val()) *
parseInt($("#threads").val());
+ var initInterface_s390x = function(result) {
+ $('#form-template-interface-s390x').show();
+ $('#form-template-interface').hide();
+ var networkItemNum = 0;
+ var addInterfaceItem = function(networkData) {
+ var networkName = networkData.networkV;
+ var nodeInterface =
$.parseHTML(wok.substitute($('#template-interface-s390x-tmpl').html(),
networkData));
+ $('.template-tab-body',
'#form-template-interface-s390x').append(nodeInterface);
+ $('.delete',
'#form-template-interface-s390x').on("click", function(event) {
+ event.preventDefault();
+ $(this).parent().parent().remove();
+ });
+
+ //initialize type option
+ var typeOptionsdata = {};
+ var typeOptions = '';
+ typeOptionsdata.macvtap = 'macvtap';
+ typeOptionsdata.ovs = 'ovs';
+ typeOptionsdata.network = 'network';
+
+ $.each(typeOptionsdata, function(key, value) {
+ if (value === networkData.type) {
+ typeOptions += '<option value="' + key +
'" selected="selected">' + networkData.type +
'</option>';
+ } else {
+ typeOptions += '<option value="' + key +
'">' + value + '</option>';
+ }
+ });
+
+ $('select', '#form-template-interface-s390x #networkID'
+ networkItemNum + ' span.type').append(typeOptions);
+ $('select', '#form-template-interface-s390x #networkID'
+ networkItemNum + ' span.type').on('change', function() {
+ var itemNode = $(this).closest('div.item');
+
+ switch ($(this).val()) {
+ case 'macvtap':
+ $('span.mode .label-mode',
itemNode).addClass('hide');
+ $('span.mode .bootstrap-select',
itemNode).toggleClass("hide", false);
+
+ var networkOptions = '';
+ for (var i = 0; i < origmacvtapNetworks.length; i++) {
+ networkOptions += '<option>' +
origmacvtapNetworks[i].name + '</option>';
+ }
+
+ $('span.network select',
itemNode).empty().append(networkOptions);
+ $('span.network select',
itemNode).selectpicker('refresh');
+
+ break;
+ case 'ovs':
+ $('span.mode .label-mode',
itemNode).removeClass('hide');
+ $('span.mode .bootstrap-select',
itemNode).toggleClass("hide", true);
+ var networkOptions = '';
+ for (var i = 0; i < origovsNetworks.length; i++) {
+ networkOptions += '<option>' +
origovsNetworks[i] + '</option>';
+ }
+
+ $('span.network select',
itemNode).empty().append(networkOptions);
+ $('span.network select',
itemNode).selectpicker('refresh');
+
+ break;
+ case 'network':
+ $('span.mode .label-mode',
itemNode).removeClass('hide');
+ $('span.mode .bootstrap-select',
itemNode).toggleClass("hide", true);
+
+ var networkOptions = '';
+ for (var i = 0; i < result.length; i++) {
+ if (result[i].state === "active") {
+ networkOptions += '<option>' +
result[i].name + '</option>';
+ }
+ }
+ $('span.network select',
itemNode).empty().append(networkOptions);
+ $('span.network select',
itemNode).selectpicker('refresh');
+ break;
+ }
+ });
+
+ switch (networkData.type) {
+ case 'macvtap':
+ //initialize network option
+ var networkOptions = '';
+ for (var i = 0; i < origmacvtapNetworks.length; i++) {
+ if (networkName === origmacvtapNetworks[i].name) {
+ networkOptions += '<option
selected="selected">' + origmacvtapNetworks[i].name +
'</option>';
+ }
+ networkOptions += '<option>' +
origmacvtapNetworks[i].name + '</option>';
+ }
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.network').append(networkOptions);
+
+ //initialize Mode option for Macvtap
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.mode').val(networkData.mode);
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.mode').selectpicker('refresh');
+
+ $('span.mode .label-mode',
nodeInterface).addClass('hide');
+ $('span.mode .bootstrap-select',
nodeInterface).removeClass("hide");
+
+ break;
+ case 'ovs':
+ var networkOptions = '';
+ for (var i = 0; i < origovsNetworks.length; i++) {
+ if (networkName === origovsNetworks[i]) {
+ networkOptions += '<option
selected="selected">' + origovsNetworks[i] + '</option>';
+ }
+ networkOptions += '<option>' +
origovsNetworks[i] + '</option>';
+ }
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.network').append(networkOptions);
+
+ //initialize Mode option for ovs
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.mode').selectpicker('refresh');
+ $('span.mode .label-mode',
nodeInterface).removeClass('hide');
+ $('span.mode .bootstrap-select',
nodeInterface).addClass("hide");
+ break;
+ case 'network':
+ var networkOptions = '';
+ for (var i = 0; i < result.length; i++) {
+ if (networkName === result[i].name) {
+ networkOptions += '<option
selected="selected">' + result[i].name + '</option>';
+ }
+ if (result[i].state === "active" &&
networkName !== result[i].name) {
+ networkOptions += '<option>' +
result[i].name + '</option>';
+ }
+ }
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.network').append(networkOptions);
+
+ //initialize Mode option for Network
+ $('select', '#form-template-interface-s390x
#networkID' + networkItemNum + ' span.mode').selectpicker('refresh');
+ $('span.mode .label-mode',
nodeInterface).removeClass('hide');
+ $('span.mode .bootstrap-select',
nodeInterface).addClass("hide");
+ break;
+ }
+ $('select', '#form-template-interface-s390x #networkID'
+ networkItemNum).selectpicker();
+ networkItemNum += 1;
+ };
+ if (origInterfaces && origInterfaces.length > 0) {
+ for (var i = 0; i < origInterfaces.length; i++) {
+ addInterfaceItem({
+ networkID: 'networkID' + networkItemNum,
+ networkV: origInterfaces[i].name,
+ type: origInterfaces[i].type,
+ mode: origInterfaces[i].mode
+ });
+ }
+ }
+ if (result && result.length > 0) {
+ for (var i = 0; i < origNetworks.length; i++) {
+ addInterfaceItem({
+ networkID: 'networkID' + networkItemNum,
+ networkV: origNetworks[i],
+ type: 'network'
+ });
+ }
+ }
+ $('#template-edit-interface-add-button-s390x').on("click",
function(event) {
+ event.preventDefault();
+ addInterfaceItem({
+ networkID: 'networkID' + networkItemNum,
+ networkV: 'default',
+ type: 'network',
+ mode: 'None'
+ });
+ });
+ };
+
+ var initProcessor = function(){
+ var setCPUValue = function(){
+
if(!$('#cores').hasClass("invalid-field")&&$('#cores').val()!=""){
+ var computedCpu =
parseInt($("#cores").val())*parseInt($("#threads").val());
$("#vcpus").val(computedCpu);
if ($("#cpus-check").prop("checked")) {
//If topology is checked, set maxcpu to be the same as # of cpu
otherwise, backend gives error
@@ -340,11 +506,23 @@ kimchi.template_edit_main = function() {
});
}
- kimchi.listNetworks(initInterface);
+ if(kimchi.hostarch === s390xArch){
+ kimchi.listmacvtapNetworks(function(macvtapnet){
+ origmacvtapNetworks = macvtapnet;
+ kimchi.listovsNetworks(function(ovsnet){
+ origovsNetworks = ovsnet;
+ kimchi.listNetworks(initInterface_s390x);
+ });
+ });
+ }else {
+ kimchi.listNetworks(initInterface);
+ }
+
kimchi.listStoragePools(initStorage);
initProcessor();
checkInvalids();
};
+
kimchi.retrieveTemplate(kimchi.selectedTemplate, initTemplate);
$('#tmpl-edit-button-save').on('click', function() {
@@ -432,18 +610,65 @@ kimchi.template_edit_main = function() {
topology: {}
};
}
- var networks = $('.template-tab-body .item',
'#form-template-interface');
- var networkForUpdate = new Array();
- $.each(networks, function(index, networkEntities) {
- var thisValue = $('select', networkEntities).val();
- networkForUpdate.push(thisValue);
+
+ if(kimchi.hostarch === s390xArch){
+ var interfaces = $('.template-tab-body .item',
'#form-template-interface-s390x');
+ var networkForUpdate = new Array();
+ var interfacceForUpdate = new Array();
+
+ $.each(interfaces, function(index, interfaceEntities) {
+ var fields = $('span.type select', interfaceEntities);
+ switch(fields.val()){
+ case 'network':
+ var thisValue = $('span.network select',
interfaceEntities).val();
+ networkForUpdate.push(thisValue);
+ break;
+ case 'macvtap':
+ var thisdata = {};
+ thisdata.type = $('span.type select',
interfaceEntities).val();
+ thisdata.name = $('span.network select',
interfaceEntities).val();
+ thisdata.mode = $('span.mode select',
interfaceEntities).val();
+ interfacceForUpdate.push(thisdata);
+ break;
+ case 'ovs':
+ var thisdata = {};
+ thisdata.type = $('span.type select',
interfaceEntities).val();
+ thisdata.name = $('span.network select',
interfaceEntities).val();
+ interfacceForUpdate.push(thisdata);
+ break;
+ }
+
+ if (networkForUpdate instanceof Array) {
+ data.networks = networkForUpdate;
+ } else if (networkForUpdate != null) {
+ data.networks = [networkForUpdate];
+ } else {
+ data.networks = [];
+ }
+
+ if (networkForUpdate instanceof Array) {
+ data.interfaces = interfacceForUpdate;
+ } else if (interfacceForUpdate != null) {
+ data.interfaces = [interfacceForUpdate];
+ } else {
+ data.interfaces = [];
+ }
});
- if (networkForUpdate instanceof Array) {
- data.networks = networkForUpdate;
- } else if (networkForUpdate != null) {
- data.networks = [networkForUpdate];
- } else {
- data.networks = [];
+ }else {
+ var networks = $('.template-tab-body .item',
'#form-template-interface');
+ var networkForUpdate = new Array();
+ $.each(networks, function(index, networkEntities) {
+ var thisValue = $('select', networkEntities).val();
+ networkForUpdate.push(thisValue);
+ });
+
+ if (networkForUpdate instanceof Array) {
+ data.networks = networkForUpdate;
+ } else if (networkForUpdate != null) {
+ data.networks = [networkForUpdate];
+ } else {
+ data.networks = [];
+ }
}
if ($('.has-error', '#form-template-storage').length) {
diff --git a/ui/pages/template-edit.html.tmpl b/ui/pages/template-edit.html.tmpl
index 6cac885..8591561 100644
--- a/ui/pages/template-edit.html.tmpl
+++ b/ui/pages/template-edit.html.tmpl
@@ -129,6 +129,15 @@
</div>
<div class="template-tab-body"></div>
</form>
+ <form id="form-template-interface-s390x"
style="display:none">
+ <div class="template-tab-header">
+ <span class="template-interface-cell
type">$_("Type")</span>
+ <span class="template-interface-cell
network">$_("Network/Interface")</span>
+ <span class="template-interface-cell
mode">$_("Mode")</span>
+ <button type="button"
id="template-edit-interface-add-button-s390x" class="pull-right btn
btn-primary"><i class="fa fa-plus-circle"></i> $_("Add
Interface")</button>
+ </div>
+ <div class="template-tab-body"></div>
+ </form>
</div>
<div role="tabpanel" class="tab-pane"
id="processor">
<form id="form-template-processor">
@@ -221,5 +230,25 @@
</span>
</div>
</script>
+<script id="template-interface-s390x-tmpl" type="text/html">
+ <div class="item" id={networkID}>
+ <span class="template-interface-cell type">
+ <select></select>
+ </span>
+ <span class="template-interface-cell network">
+ <select></select>
+ </span>
+ <span class="template-interface-cell mode">
+ <span class="label-mode hide">None</span>
+ <select>
+ <option value="bridge">bridge</option>
+ <option value="vepa">vepa</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>
</body>
</html>