From 876e93b441f5042fb872fd7e01c1e793988e0915 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 9 Apr 2013 14:15:29 -0700 Subject: [PATCH 01/76] VM multiple NICs: Fix broken UI due to API call changes --- ui/scripts/network.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/scripts/network.js b/ui/scripts/network.js index cc1aad34927..6f6a073812f 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -1186,7 +1186,7 @@ virtualmachineid: args.context.instances[0].id }, success: function(json) { - var ips = json.listnics.nic ? json.listnics.nic[0].secondaryip : []; + var ips = json.listnicsresponse.nic ? json.listnicsresponse.nic[0].secondaryip : []; args.response.success({ data: $(ips).map(function(index, ip) { @@ -1252,7 +1252,7 @@ virtualmachineid: args.context.instances[0].id }, success: function(json) { - var ips = json.listnics.nic[0].secondaryip + var ips = json.listnicsresponse.nic[0].secondaryip args.response.success({ data: $.grep($(ips).map(function(index, ip) { From e0692b39d9409fb2913b26533790f495d17beaf4 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 9 Apr 2013 14:16:01 -0700 Subject: [PATCH 02/76] List view UI: Fix 'no data to show' message not appearing in some cases --- ui/scripts/ui/widgets/listView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 4b88647e6f1..1c74056c75b 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -863,7 +863,7 @@ var uiCustom = listViewArgs.uiCustom; var subselect = uiCustom ? listViewArgs.listView.subselect : null; - if (!data || ($.isArray(data) && !data.length)) { + if (!data || !data.length) { if (!$tbody.find('tr').size()) { return [ $('').addClass('empty').append( From 9d5c375678fd7477361b8f6aaab914ba682e4cf8 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 9 Apr 2013 14:52:06 -0700 Subject: [PATCH 03/76] Instance wizard: clean up JS formatting --- ui/scripts/instanceWizard.js | 924 +++++++++++++++++------------------ 1 file changed, 462 insertions(+), 462 deletions(-) diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js index e1aeafde67c..277719c0acb 100644 --- a/ui/scripts/instanceWizard.js +++ b/ui/scripts/instanceWizard.js @@ -68,475 +68,475 @@ // Data providers for each wizard step steps: [ - - // Step 1: Setup - function(args) { - if(args.initArgs.pluginForm != null && args.initArgs.pluginForm.name == "vpcTierInstanceWizard") { //from VPC Tier chart - //populate only one zone to the dropdown, the zone which the VPC is under. - zoneObjs = [{ - id: args.context.vpc[0].zoneid, - name: args.context.vpc[0].zonename, - networktype: 'Advanced' - }]; - args.response.success({ data: {zones: zoneObjs}}); - } - else { //from Instance page - $.ajax({ - url: createURL("listZones&available=true"), - dataType: "json", - async: false, - success: function(json) { - zoneObjs = json.listzonesresponse.zone; - args.response.success({ data: {zones: zoneObjs}}); - } - }); - } - }, + + // Step 1: Setup + function(args) { + if(args.initArgs.pluginForm != null && args.initArgs.pluginForm.name == "vpcTierInstanceWizard") { //from VPC Tier chart + //populate only one zone to the dropdown, the zone which the VPC is under. + zoneObjs = [{ + id: args.context.vpc[0].zoneid, + name: args.context.vpc[0].zonename, + networktype: 'Advanced' + }]; + args.response.success({ data: {zones: zoneObjs}}); + } + else { //from Instance page + $.ajax({ + url: createURL("listZones&available=true"), + dataType: "json", + async: false, + success: function(json) { + zoneObjs = json.listzonesresponse.zone; + args.response.success({ data: {zones: zoneObjs}}); + } + }); + } + }, - // Step 2: Select template - function(args) { - $(zoneObjs).each(function(){ - if(this.id == args.currentData.zoneid) { - selectedZoneObj = this; - return false; //break the $.each() loop - } - }); - if(selectedZoneObj == null) { - alert("error: can't find matched zone object"); - return; - } - - $.ajax({ - url: createURL("listHypervisors&zoneid="+args.currentData.zoneid), - dataType: "json", - async: false, - success: function(json) { - hypervisorObjs = json.listhypervisorsresponse.hypervisor; - } - }); - - //***** get templates/ISOs (begin) ***** - var selectedTemplate = args.currentData['select-template']; - if (selectedTemplate == 'select-template') { - var hypervisorArray = []; - $(hypervisorObjs).each(function(index, item) { - hypervisorArray.push(item.name); - }); - - $.ajax({ - url: createURL("listTemplates&templatefilter=featured&zoneid="+args.currentData.zoneid), - dataType: "json", - async: false, - success: function(json) { - if(json.listtemplatesresponse.template == null) { - featuredTemplateObjs = null; - } - else { - featuredTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { - if($.inArray(item.hypervisor, hypervisorArray) > -1) - return true; - }); - } + // Step 2: Select template + function(args) { + $(zoneObjs).each(function(){ + if(this.id == args.currentData.zoneid) { + selectedZoneObj = this; + return false; //break the $.each() loop } }); + if(selectedZoneObj == null) { + alert("error: can't find matched zone object"); + return; + } + $.ajax({ - url: createURL("listTemplates&templatefilter=community&zoneid="+args.currentData.zoneid), + url: createURL("listHypervisors&zoneid="+args.currentData.zoneid), dataType: "json", async: false, success: function(json) { - if(json.listtemplatesresponse.template == null) { - communityTemplateObjs = null; - } - else { - communityTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { - if($.inArray(item.hypervisor, hypervisorArray) > -1) - return true; - }); - } + hypervisorObjs = json.listhypervisorsresponse.hypervisor; } }); - $.ajax({ - url: createURL("listTemplates&templatefilter=selfexecutable&zoneid="+args.currentData.zoneid), - dataType: "json", - async: false, - success: function(json) { - if(json.listtemplatesresponse.template == null) { - myTemplateObjs = null; - } - else { - myTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { - if($.inArray(item.hypervisor, hypervisorArray) > -1) - return true; - }); - } - } - }); - } else if (selectedTemplate == 'select-iso') { - $.ajax({ - url: createURL("listIsos&isofilter=featured&zoneid=" + args.currentData.zoneid + "&bootable=true"), - dataType: "json", - async: false, - success: function(json) { - if(json.listisosresponse.iso == null) { - featuredIsoObjs = null; - } - else { - featuredIsoObjs = json.listisosresponse.iso; - } - } - }); - $.ajax({ - url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"), - dataType: "json", - async: false, - success: function(json) { - if(json.listisosresponse.iso == null) { - communityIsoObjs = null; - } - else { - communityIsoObjs = json.listisosresponse.iso; - } - } - }); - $.ajax({ - url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"), - dataType: "json", - async: false, - success: function(json) { - if(json.listisosresponse.iso == null) { - myIsoObjs = null; - } - else { - myIsoObjs = json.listisosresponse.iso; - } - } - }); - } - //***** get templates/ISOs (end) ***** + //***** get templates/ISOs (begin) ***** + var selectedTemplate = args.currentData['select-template']; + if (selectedTemplate == 'select-template') { + var hypervisorArray = []; + $(hypervisorObjs).each(function(index, item) { + hypervisorArray.push(item.name); + }); - var templatesObj = {}; - if (selectedTemplate == 'select-template') { - templatesObj = { - featuredtemplates: featuredTemplateObjs, - communitytemplates: communityTemplateObjs, - mytemplates: myTemplateObjs - } - } else if (selectedTemplate == 'select-iso') { - templatesObj = { - featuredisos: featuredIsoObjs, - communityisos: communityIsoObjs, - myisos: myIsoObjs - } - } - args.response.success({ - hypervisor: { - idField: 'name', - nameField: 'name' - }, - data: { - templates: templatesObj, - hypervisors: hypervisorObjs - } - }); - }, - - // Step 3: Service offering - function(args) { - if(args.currentData["select-template"] == "select-template") { - if(featuredTemplateObjs != null && featuredTemplateObjs.length > 0) { - for(var i=0; i < featuredTemplateObjs.length; i++) { - if(featuredTemplateObjs[i].id == args.currentData.templateid) { - selectedTemplateObj = featuredTemplateObjs[i]; - break; + $.ajax({ + url: createURL("listTemplates&templatefilter=featured&zoneid="+args.currentData.zoneid), + dataType: "json", + async: false, + success: function(json) { + if(json.listtemplatesresponse.template == null) { + featuredTemplateObjs = null; + } + else { + featuredTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { + if($.inArray(item.hypervisor, hypervisorArray) > -1) + return true; + }); + } } + }); + $.ajax({ + url: createURL("listTemplates&templatefilter=community&zoneid="+args.currentData.zoneid), + dataType: "json", + async: false, + success: function(json) { + if(json.listtemplatesresponse.template == null) { + communityTemplateObjs = null; + } + else { + communityTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { + if($.inArray(item.hypervisor, hypervisorArray) > -1) + return true; + }); + } + } + }); + $.ajax({ + url: createURL("listTemplates&templatefilter=selfexecutable&zoneid="+args.currentData.zoneid), + dataType: "json", + async: false, + success: function(json) { + if(json.listtemplatesresponse.template == null) { + myTemplateObjs = null; + } + else { + myTemplateObjs = $.grep(json.listtemplatesresponse.template, function(item, index) { + if($.inArray(item.hypervisor, hypervisorArray) > -1) + return true; + }); + } + } + }); + } else if (selectedTemplate == 'select-iso') { + $.ajax({ + url: createURL("listIsos&isofilter=featured&zoneid=" + args.currentData.zoneid + "&bootable=true"), + dataType: "json", + async: false, + success: function(json) { + if(json.listisosresponse.iso == null) { + featuredIsoObjs = null; + } + else { + featuredIsoObjs = json.listisosresponse.iso; + } + } + }); + $.ajax({ + url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"), + dataType: "json", + async: false, + success: function(json) { + if(json.listisosresponse.iso == null) { + communityIsoObjs = null; + } + else { + communityIsoObjs = json.listisosresponse.iso; + } + } + }); + $.ajax({ + url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"), + dataType: "json", + async: false, + success: function(json) { + if(json.listisosresponse.iso == null) { + myIsoObjs = null; + } + else { + myIsoObjs = json.listisosresponse.iso; + } + } + }); + } + //***** get templates/ISOs (end) ***** + + + var templatesObj = {}; + if (selectedTemplate == 'select-template') { + templatesObj = { + featuredtemplates: featuredTemplateObjs, + communitytemplates: communityTemplateObjs, + mytemplates: myTemplateObjs + } + } else if (selectedTemplate == 'select-iso') { + templatesObj = { + featuredisos: featuredIsoObjs, + communityisos: communityIsoObjs, + myisos: myIsoObjs } } - if(selectedTemplateObj == null) { - if(communityTemplateObjs != null && communityTemplateObjs.length > 0) { - for(var i=0; i < communityTemplateObjs.length; i++) { - if(communityTemplateObjs[i].id == args.currentData.templateid) { - selectedTemplateObj = communityTemplateObjs[i]; + args.response.success({ + hypervisor: { + idField: 'name', + nameField: 'name' + }, + data: { + templates: templatesObj, + hypervisors: hypervisorObjs + } + }); + }, + + // Step 3: Service offering + function(args) { + if(args.currentData["select-template"] == "select-template") { + if(featuredTemplateObjs != null && featuredTemplateObjs.length > 0) { + for(var i=0; i < featuredTemplateObjs.length; i++) { + if(featuredTemplateObjs[i].id == args.currentData.templateid) { + selectedTemplateObj = featuredTemplateObjs[i]; break; } } } - } - if(selectedTemplateObj == null) { - if(myTemplateObjs != null && myTemplateObjs.length > 0) { - for(var i=0; i < myTemplateObjs.length; i++) { - if(myTemplateObjs[i].id == args.currentData.templateid) { - selectedTemplateObj = myTemplateObjs[i]; - break; - } - } - } - } - if(selectedTemplateObj == null) - alert("unable to find matched template object"); - else - selectedHypervisor = selectedTemplateObj.hypervisor; - } - else { //(args.currentData["select-template"] == "select-iso" - selectedHypervisor = args.currentData.hypervisorid; - } - - $.ajax({ - url: createURL("listServiceOfferings&issystem=false"), - dataType: "json", - async: true, - success: function(json) { - serviceOfferingObjs = json.listserviceofferingsresponse.serviceoffering; - args.response.success({ - data: {serviceOfferings: serviceOfferingObjs} - }); - } - }); - }, - - // Step 4: Data disk offering - function(args) { - var isRequred = (args.currentData["select-template"] == "select-iso"? true: false); - $.ajax({ - url: createURL("listDiskOfferings"), - dataType: "json", - async: true, - success: function(json) { - diskOfferingObjs = json.listdiskofferingsresponse.diskoffering; - args.response.success({ - required: isRequred, - customFlag: 'iscustomized', // Field determines if custom slider is shown - data: {diskOfferings: diskOfferingObjs} - }); - } - }); - }, - - // Step 5: Network - function(args) { - if(diskOfferingObjs != null && diskOfferingObjs.length > 0) { - for(var i=0; i < diskOfferingObjs.length; i++) { - if(diskOfferingObjs[i].id == args.currentData.diskofferingid) { - selectedDiskOfferingObj = diskOfferingObjs[i]; - break; - } - } - } - - if (selectedZoneObj.networktype == "Advanced") { //Advanced zone. Show network list. - var $networkStep = $(".step.network:visible .nothing-to-select"); - var $networkStepContainer = $('.step.network:visible'); - - if(args.initArgs.pluginForm != null && args.initArgs.pluginForm.name == "vpcTierInstanceWizard") { //from VPC Tier chart - step5ContainerType = 'nothing-to-select'; - $networkStep.find("#from_instance_page_1").hide(); - $networkStep.find("#from_instance_page_2").hide(); - $networkStep.find("#from_vpc_tier").text("tier " + args.context.networks[0].name); - $networkStep.find("#from_vpc_tier").show(); - } else { //from Instance page - if(selectedZoneObj.securitygroupsenabled != true) { // Advanced SG-disabled zone - step5ContainerType = 'select-network'; - $networkStep.find("#from_instance_page_1").show(); - $networkStep.find("#from_instance_page_2").show(); - $networkStep.find("#from_vpc_tier").text(""); - $networkStep.find("#from_vpc_tier").hide(); - $networkStepContainer.removeClass('next-use-security-groups'); - } else { // Advanced SG-enabled zone - step5ContainerType = 'select-advanced-sg'; - } - - if ($networkStepContainer.hasClass('next-use-security-groups')) { - $networkStepContainer.removeClass('repeat next-use-security-groups loaded'); - step5ContainerType = 'select-security-group'; - } - } - } - else { //Basic zone. Show securigy group list or nothing(when no SecurityGroup service in guest network) - var includingSecurityGroupService = false; - $.ajax({ - url: createURL("listNetworks&trafficType=Guest&zoneId=" + selectedZoneObj.id), - dataType: "json", - async: false, - success: function(json) { - //basic zone should have only one guest network returned in this API call - var items = json.listnetworksresponse.network; - if(items != null && items.length > 0) { - var networkObj = items[0]; //basic zone has only one guest network - var serviceObjArray = networkObj.service; - for(var k = 0; k < serviceObjArray.length; k++) { - if(serviceObjArray[k].name == "SecurityGroup") { - includingSecurityGroupService = true; + if(selectedTemplateObj == null) { + if(communityTemplateObjs != null && communityTemplateObjs.length > 0) { + for(var i=0; i < communityTemplateObjs.length; i++) { + if(communityTemplateObjs[i].id == args.currentData.templateid) { + selectedTemplateObj = communityTemplateObjs[i]; break; } } } } - }); - - if(includingSecurityGroupService == false || selectedHypervisor == "VMware") { - step5ContainerType = 'nothing-to-select'; - } - else { - step5ContainerType = 'select-security-group'; - } - } - - //step5ContainerType = 'nothing-to-select'; //for testing only, comment it out before checking in - if(step5ContainerType == 'select-network' || step5ContainerType == 'select-advanced-sg') { - var defaultNetworkArray = [], optionalNetworkArray = []; - var networkData = { - zoneId: args.currentData.zoneid, - canusefordeploy: true - }; - - if(selectedZoneObj.networktype == 'Advanced' && selectedZoneObj.securitygroupsenabled == true) { - $.extend(networkData, { - type: 'Shared' - }); - } - - if (!(cloudStack.context.projects && cloudStack.context.projects[0])) { - networkData.domainid = g_domainid; - networkData.account = g_account; - } - - var vpcObjs; - - //listVPCs without account/domainid/listAll parameter will return only VPCs belonging to the current login. That's what should happen in Instances page's VM Wizard. - //i.e. If the current login is root-admin, do not show VPCs belonging to regular-user/domain-admin in Instances page's VM Wizard. - $.ajax({ - url: createURL('listVPCs'), - async: false, - success: function(json) { - vpcObjs = json.listvpcsresponse.vpc ? json.listvpcsresponse.vpc : []; - } - }); - - var networkObjsToPopulate = []; - $.ajax({ - url: createURL('listNetworks'), - data: networkData, - async: false, - success: function(json) { - networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : []; - if(networkObjs.length > 0) { - for(var i = 0; i < networkObjs.length; i++) { - var networkObj = networkObjs[i]; - var includingSecurityGroup = false; - var serviceObjArray = networkObj.service; - for(var k = 0; k < serviceObjArray.length; k++) { - if(serviceObjArray[k].name == "SecurityGroup") { - networkObjs[i].type = networkObjs[i].type + ' (sg)'; - includingSecurityGroup = true; - break; - } - } - - if (networkObj.vpcid) { - networkObj._singleSelect = true; + if(selectedTemplateObj == null) { + if(myTemplateObjs != null && myTemplateObjs.length > 0) { + for(var i=0; i < myTemplateObjs.length; i++) { + if(myTemplateObjs[i].id == args.currentData.templateid) { + selectedTemplateObj = myTemplateObjs[i]; + break; } - - //for Advanced SG-enabled zone, list only SG network offerings - if(selectedZoneObj.networktype == 'Advanced' && selectedZoneObj.securitygroupsenabled == true) { - if(includingSecurityGroup == false) - continue; //skip to next network offering - } - networkObjsToPopulate.push(networkObj); - } - } - } - }); - - $.ajax({ - url: createURL("listNetworkOfferings"), - dataType: "json", - data: { - forvpc: false, - zoneid: args.currentData.zoneid, - guestiptype: 'Isolated', - supportedServices: 'SourceNat', - specifyvlan: false, - state: 'Enabled' - }, - async: false, - success: function(json) { - networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; - } - }); - //get network offerings (end) *** - - $networkStepContainer.removeClass('repeat next-use-security-groups'); - - if (step5ContainerType == 'select-advanced-sg') { - $networkStepContainer.addClass('repeat next-use-security-groups'); - - // Add guest network is disabled - $networkStepContainer.find('.select-network').addClass('no-add-network'); - } else { - $networkStepContainer.find('.select-network').removeClass('no-add-network'); - } - - args.response.success({ - type: 'select-network', - data: { - networkObjs: networkObjsToPopulate, - securityGroups: [], - networkOfferings: networkOfferingObjs, - vpcs: vpcObjs - } - }); - } - - else if(step5ContainerType == 'select-security-group') { - var securityGroupArray = []; - var data = { - domainid: g_domainid, - account: g_account - }; - - $.ajax({ - url: createURL("listSecurityGroups"), - dataType: "json", - async: false, - data: cloudStack.context.projects ? {} : data, - success: function(json) { - var items = json.listsecuritygroupsresponse.securitygroup; - if (items != null && items.length > 0) { - for (var i = 0; i < items.length; i++) { - securityGroupArray.push(items[i]); } } } - }); - args.response.success({ - type: 'select-security-group', - data: { - networkObjs: [], - securityGroups: securityGroupArray, - networkOfferings: [], - vpcs: [] + if(selectedTemplateObj == null) + alert("unable to find matched template object"); + else + selectedHypervisor = selectedTemplateObj.hypervisor; + } + else { //(args.currentData["select-template"] == "select-iso" + selectedHypervisor = args.currentData.hypervisorid; + } + + $.ajax({ + url: createURL("listServiceOfferings&issystem=false"), + dataType: "json", + async: true, + success: function(json) { + serviceOfferingObjs = json.listserviceofferingsresponse.serviceoffering; + args.response.success({ + data: {serviceOfferings: serviceOfferingObjs} + }); } }); - } + }, - else if(step5ContainerType == 'nothing-to-select') { - args.response.success({ - type: 'nothing-to-select', - data: { - networkObjs: [], - securityGroups: [], - networkOfferings: [], - vpcs: [] + // Step 4: Data disk offering + function(args) { + var isRequred = (args.currentData["select-template"] == "select-iso"? true: false); + $.ajax({ + url: createURL("listDiskOfferings"), + dataType: "json", + async: true, + success: function(json) { + diskOfferingObjs = json.listdiskofferingsresponse.diskoffering; + args.response.success({ + required: isRequred, + customFlag: 'iscustomized', // Field determines if custom slider is shown + data: {diskOfferings: diskOfferingObjs} + }); } }); + }, + + // Step 6: Network + function(args) { + if(diskOfferingObjs != null && diskOfferingObjs.length > 0) { + for(var i=0; i < diskOfferingObjs.length; i++) { + if(diskOfferingObjs[i].id == args.currentData.diskofferingid) { + selectedDiskOfferingObj = diskOfferingObjs[i]; + break; + } + } + } + + if (selectedZoneObj.networktype == "Advanced") { //Advanced zone. Show network list. + var $networkStep = $(".step.network:visible .nothing-to-select"); + var $networkStepContainer = $('.step.network:visible'); + + if(args.initArgs.pluginForm != null && args.initArgs.pluginForm.name == "vpcTierInstanceWizard") { //from VPC Tier chart + step5ContainerType = 'nothing-to-select'; + $networkStep.find("#from_instance_page_1").hide(); + $networkStep.find("#from_instance_page_2").hide(); + $networkStep.find("#from_vpc_tier").text("tier " + args.context.networks[0].name); + $networkStep.find("#from_vpc_tier").show(); + } else { //from Instance page + if(selectedZoneObj.securitygroupsenabled != true) { // Advanced SG-disabled zone + step5ContainerType = 'select-network'; + $networkStep.find("#from_instance_page_1").show(); + $networkStep.find("#from_instance_page_2").show(); + $networkStep.find("#from_vpc_tier").text(""); + $networkStep.find("#from_vpc_tier").hide(); + $networkStepContainer.removeClass('next-use-security-groups'); + } else { // Advanced SG-enabled zone + step5ContainerType = 'select-advanced-sg'; + } + + if ($networkStepContainer.hasClass('next-use-security-groups')) { + $networkStepContainer.removeClass('repeat next-use-security-groups loaded'); + step5ContainerType = 'select-security-group'; + } + } + } + else { //Basic zone. Show securigy group list or nothing(when no SecurityGroup service in guest network) + var includingSecurityGroupService = false; + $.ajax({ + url: createURL("listNetworks&trafficType=Guest&zoneId=" + selectedZoneObj.id), + dataType: "json", + async: false, + success: function(json) { + //basic zone should have only one guest network returned in this API call + var items = json.listnetworksresponse.network; + if(items != null && items.length > 0) { + var networkObj = items[0]; //basic zone has only one guest network + var serviceObjArray = networkObj.service; + for(var k = 0; k < serviceObjArray.length; k++) { + if(serviceObjArray[k].name == "SecurityGroup") { + includingSecurityGroupService = true; + break; + } + } + } + } + }); + + if(includingSecurityGroupService == false || selectedHypervisor == "VMware") { + step5ContainerType = 'nothing-to-select'; + } + else { + step5ContainerType = 'select-security-group'; + } + } + + //step5ContainerType = 'nothing-to-select'; //for testing only, comment it out before checking in + if(step5ContainerType == 'select-network' || step5ContainerType == 'select-advanced-sg') { + var defaultNetworkArray = [], optionalNetworkArray = []; + var networkData = { + zoneId: args.currentData.zoneid, + canusefordeploy: true + }; + + if(selectedZoneObj.networktype == 'Advanced' && selectedZoneObj.securitygroupsenabled == true) { + $.extend(networkData, { + type: 'Shared' + }); + } + + if (!(cloudStack.context.projects && cloudStack.context.projects[0])) { + networkData.domainid = g_domainid; + networkData.account = g_account; + } + + var vpcObjs; + + //listVPCs without account/domainid/listAll parameter will return only VPCs belonging to the current login. That's what should happen in Instances page's VM Wizard. + //i.e. If the current login is root-admin, do not show VPCs belonging to regular-user/domain-admin in Instances page's VM Wizard. + $.ajax({ + url: createURL('listVPCs'), + async: false, + success: function(json) { + vpcObjs = json.listvpcsresponse.vpc ? json.listvpcsresponse.vpc : []; + } + }); + + var networkObjsToPopulate = []; + $.ajax({ + url: createURL('listNetworks'), + data: networkData, + async: false, + success: function(json) { + networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : []; + if(networkObjs.length > 0) { + for(var i = 0; i < networkObjs.length; i++) { + var networkObj = networkObjs[i]; + var includingSecurityGroup = false; + var serviceObjArray = networkObj.service; + for(var k = 0; k < serviceObjArray.length; k++) { + if(serviceObjArray[k].name == "SecurityGroup") { + networkObjs[i].type = networkObjs[i].type + ' (sg)'; + includingSecurityGroup = true; + break; + } + } + + if (networkObj.vpcid) { + networkObj._singleSelect = true; + } + + //for Advanced SG-enabled zone, list only SG network offerings + if(selectedZoneObj.networktype == 'Advanced' && selectedZoneObj.securitygroupsenabled == true) { + if(includingSecurityGroup == false) + continue; //skip to next network offering + } + networkObjsToPopulate.push(networkObj); + } + } + } + }); + + $.ajax({ + url: createURL("listNetworkOfferings"), + dataType: "json", + data: { + forvpc: false, + zoneid: args.currentData.zoneid, + guestiptype: 'Isolated', + supportedServices: 'SourceNat', + specifyvlan: false, + state: 'Enabled' + }, + async: false, + success: function(json) { + networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; + } + }); + //get network offerings (end) *** + + $networkStepContainer.removeClass('repeat next-use-security-groups'); + + if (step5ContainerType == 'select-advanced-sg') { + $networkStepContainer.addClass('repeat next-use-security-groups'); + + // Add guest network is disabled + $networkStepContainer.find('.select-network').addClass('no-add-network'); + } else { + $networkStepContainer.find('.select-network').removeClass('no-add-network'); + } + + args.response.success({ + type: 'select-network', + data: { + networkObjs: networkObjsToPopulate, + securityGroups: [], + networkOfferings: networkOfferingObjs, + vpcs: vpcObjs + } + }); + } + + else if(step5ContainerType == 'select-security-group') { + var securityGroupArray = []; + var data = { + domainid: g_domainid, + account: g_account + }; + + $.ajax({ + url: createURL("listSecurityGroups"), + dataType: "json", + async: false, + data: cloudStack.context.projects ? {} : data, + success: function(json) { + var items = json.listsecuritygroupsresponse.securitygroup; + if (items != null && items.length > 0) { + for (var i = 0; i < items.length; i++) { + securityGroupArray.push(items[i]); + } + } + } + }); + args.response.success({ + type: 'select-security-group', + data: { + networkObjs: [], + securityGroups: securityGroupArray, + networkOfferings: [], + vpcs: [] + } + }); + } + + else if(step5ContainerType == 'nothing-to-select') { + args.response.success({ + type: 'nothing-to-select', + data: { + networkObjs: [], + securityGroups: [], + networkOfferings: [], + vpcs: [] + } + }); + } + + }, + + // Step 6: Review + function(args) { + return false; } - - }, - - // Step 6: Review - function(args) { - return false; - } ], action: function(args) { // Create a new VM!!!! @@ -638,12 +638,12 @@ if(checkedSecurityGroupIdArray.length > 0) array1.push("&securitygroupids=" + checkedSecurityGroupIdArray.join(",")); - + if(selectedZoneObj.networktype == "Advanced" && selectedZoneObj.securitygroupsenabled == true) { // Advanced SG-enabled zone var array2 = []; var myNetworks = $('.multi-wizard:visible form').data('my-networks'); //widget limitation: If using an advanced security group zone, get the guest networks like this var defaultNetworkId = $('.multi-wizard:visible form').find('input[name=defaultNetwork]:checked').val(); - + var checkedNetworkIdArray; if(typeof(myNetworks) == "object" && myNetworks.length != null) { //myNetworks is an array of string, e.g. ["203", "202"], checkedNetworkIdArray = myNetworks; @@ -703,30 +703,30 @@ var vmid = json.deployvirtualmachineresponse.id; args.response.success( {_custom: - {jobId: jid, - getUpdatedItem: function(json) { - var item = json.queryasyncjobresultresponse.jobresult.virtualmachine; - if (item.password != null) - alert("Password of new VM " + item.displayname + " is " + item.password); - return item; - }, - getActionFilter: function() { - return cloudStack.actionFilter.vmActionFilter; - }, - getUpdatedItemWhenAsyncJobFails: function() { - var item; - $.ajax({ - url: createURL("listVirtualMachines&id="+vmid), - dataType: "json", - async: false, - success: function(json) { - item = json.listvirtualmachinesresponse.virtualmachine[0]; - } - }); - return item; - } - } - } + {jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.virtualmachine; + if (item.password != null) + alert("Password of new VM " + item.displayname + " is " + item.password); + return item; + }, + getActionFilter: function() { + return cloudStack.actionFilter.vmActionFilter; + }, + getUpdatedItemWhenAsyncJobFails: function() { + var item; + $.ajax({ + url: createURL("listVirtualMachines&id="+vmid), + dataType: "json", + async: false, + success: function(json) { + item = json.listvirtualmachinesresponse.virtualmachine[0]; + } + }); + return item; + } + } + } ); }, error: function(XMLHttpResponse) { From e907a08fba6a4000e2f5b98192ff69066092c273 Mon Sep 17 00:00:00 2001 From: Brian Federle Date: Tue, 9 Apr 2013 15:58:29 -0700 Subject: [PATCH 04/76] Affinity UI: Add step to instance wizard --- .../classes/resources/messages.properties | 6 ++++ ui/css/cloudstack3.css | 28 ++++++++++++++++--- ui/dictionary.jsp | 6 ++++ ui/index.jsp | 13 +++++++-- ui/scripts/instanceWizard.js | 12 ++++++++ ui/scripts/ui-custom/instanceWizard.js | 19 +++++++++++++ 6 files changed, 78 insertions(+), 6 deletions(-) diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index d62cbaeb99b..abd1e300ddc 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -17,6 +17,12 @@ #new labels (begin) ********************************************************************************************** +label.affinity=Affinity +label.anti.affinity=Anti-affinity +label.affinity.groups=Affinity Groups +label.anti.affinity.groups=Anti-affinity Groups +label.affinity.group=Affinity Group +label.anti.affinity.group=Anti-affinity Group message.redirecting.region=Redirecting to region... label.use.vm.ip=Use VM IP: label.cpu.limits=CPU limits diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 7ebda9b8f36..1890476149e 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -5222,6 +5222,10 @@ label.error { position: relative; } +.multi-wizard.instance-wizard .progress ul li { + width: 109px; +} + .multi-wizard .progress ul li.first { /*+border-radius:5px 0 0 5px;*/ -moz-border-radius: 5px 0 0 5px; @@ -5263,6 +5267,10 @@ label.error { text-align: center; } +.multi-wizard.instance-wizard .progress ul li span { + left: 36px; +} + .multi-wizard .progress ul li span.multiline { width: 71px; top: 12px; @@ -5279,6 +5287,10 @@ label.error { z-index: 1000; } +.multi-wizard.instance-wizard .progress ul li span.arrow { + left: 27px; +} + .multi-wizard .progress ul li.active span.arrow { background-position: -1px -396px; } @@ -5299,6 +5311,15 @@ label.error { background: transparent; } +.multi-wizard.instance-wizard .progress ul li span.number { + left: 16px; +} + +.multi-wizard.instance-wizard .progress ul li span.multiline { + width: 79px; + left: 23px; +} + .multi-wizard .progress ul li.active span { /*+text-shadow:0px -1px 1px #004AFF;*/ -moz-text-shadow: 0px -1px 1px #004AFF; @@ -11761,12 +11782,11 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .updateResourceLimits:hover .icon { background-position: -100px -614px; } - + .addVlanRange .icon { background-position: -168px -31px; } - .addVlanRange:hover .icon { background-position: -168px -613px; } @@ -11796,8 +11816,8 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: -168px -31px; } -.reset .icon , -.scaleUp .icon{ +.reset .icon, +.scaleUp .icon { background-position: -168px -31px; } diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 11e98cf5024..ffe0e891980 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -25,6 +25,12 @@ under the License. <% long now = System.currentTimeMillis(); %> + + diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 1c4c38c75fd..b230cf72583 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -437,7 +437,6 @@ poll: pollAsyncJobResult } }, - snapshot: { messages: { notification: function(args) { @@ -500,7 +499,6 @@ pool: pollAsyncJobResult } }, - destroy: { label: 'label.action.destroy.instance', compactLabel: 'label.destroy', @@ -566,7 +564,6 @@ } } }, - reset: { label: 'Reset VM', messages:{ @@ -597,8 +594,81 @@ } } - }, + }, + changeAffinity: { + label: 'Change affinity', + + action: { + custom: cloudStack.uiCustom.affinity({ + tierSelect: function(args) { + if ('vpc' in args.context) { //from VPC section + args.$tierSelect.show(); //show tier dropdown + + $.ajax({ //populate tier dropdown + url: createURL("listNetworks"), + async: false, + data: { + vpcid: args.context.vpc[0].id, + //listAll: true, //do not pass listAll to listNetworks under VPC + domainid: args.context.vpc[0].domainid, + account: args.context.vpc[0].account, + supportedservices: 'StaticNat' + }, + success: function(json) { + var networks = json.listnetworksresponse.network; + var items = [{ id: -1, description: 'Please select a tier' }]; + $(networks).each(function(){ + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({ data: items }); + } + }); + } + else { //from Guest Network section + args.$tierSelect.hide(); + } + + args.$tierSelect.change(function() { + args.$tierSelect.closest('.list-view').listView('refresh'); + }); + args.$tierSelect.closest('.list-view').listView('refresh'); + }, + + listView: { + listView: { + id: 'affinityGroups', + fields: { + name: { label: 'label.name' }, + type: { label: 'label.type' } + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { name: 'Affinity Group 1', type: 'Affinity' }, + { name: 'Affinity Group 2', type: 'Anti-affinity' }, + { name: 'Anti-affinity Group', type: 'Anti-affinity' } + ] + }); + } + } + }, + action: function(args) { + args.response.success(); + } + }) + }, + messages: { + notification: function(args) { + return 'label.action.enable.static.NAT'; + } + }, + notification: { + poll: function(args) { + args.complete(); + } + } + }, edit: { label: 'label.edit', @@ -608,7 +678,7 @@ group: args.data.group, ostypeid: args.data.guestosid }; - + if(args.data.displayname != args.context.instances[0].displayname) { $.extend(data, { displayName: args.data.displayname @@ -1404,6 +1474,7 @@ allowedActions.push("reset"); allowedActions.push("snapshot"); allowedActions.push("scaleUp"); + allowedActions.push("changeAffinity"); if(isAdmin()) allowedActions.push("migrateToAnotherStorage"); diff --git a/ui/scripts/ui-custom/affinity.js b/ui/scripts/ui-custom/affinity.js new file mode 100644 index 00000000000..1a1eb552cba --- /dev/null +++ b/ui/scripts/ui-custom/affinity.js @@ -0,0 +1,171 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +(function(cloudStack, $) { + cloudStack.uiCustom.affinity = function(args) { + var listView = args.listView; + var action = args.action; + var tierSelect = args.tierSelect; + + return function(args) { + var context = args.context; + var $instanceRow = args.$instanceRow; + + var vmList = function(args) { + // Create a listing of instances, based on limited information + // from main instances list view + var $listView; + var instances = $.extend(true, {}, args.listView, { + context: context, + uiCustom: true + }); + + instances.listView.actions = { + select: { + label: _l('label.select.instance'), + type: 'checkbox', + action: { + uiCustom: function(args) { + var $item = args.$item; + var $input = $item.find('td.actions input:visible'); + + if ($input.attr('type') == 'checkbox') { + if ($input.is(':checked')) + $item.addClass('multi-edit-selected'); + else + $item.removeClass('multi-edit-selected'); + } else { + $item.siblings().removeClass('multi-edit-selected'); + $item.addClass('multi-edit-selected'); + } + } + } + } + }; + + $listView = $('
').listView(instances); + + // Change action label + $listView.find('th.actions').html(_l('label.select')); + + return $listView; + }; + + var $dataList = vmList({ + listView: listView + }).dialog({ + dialogClass: 'multi-edit-add-list panel', + width: 825, + title: _l('label.select.vm.for.static.nat'), + buttons: [ + { + text: _l('label.apply'), + 'class': 'ok', + click: function() { + if ($dataList.find('.tier-select select').val() == -1) { + cloudStack.dialog.notice({ message: ('Please select a tier')}); + return false; + } + + if (!$dataList.find( + 'input[type=radio]:checked, input[type=checkbox]:checked' + ).size()) { + cloudStack.dialog.notice({ message: _l('message.select.instance')}); + + return false; + } + + var complete = args.complete; + var start = args.start; + + start(); + $dataList.fadeOut(function() { + action({ + tierID: $dataList.find('.tier-select select').val(), + _subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(), + context: $.extend(true, {}, context, { + instances: [ + $dataList.find('tr.multi-edit-selected').data('json-obj') + ] + }), + response: { + success: function(args) { + complete({ + $item: $instanceRow + }); + }, + error: function(args) { + cloudStack.dialog.notice({ message: args }); + } + } + }); + $dataList.remove(); + }); + + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + } + }, + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $dataList.fadeOut(function() { + $dataList.remove(); + }); + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + } + } + ] + }).parent('.ui-dialog').overlay(); + + // Add tier select dialog + if (tierSelect) { + var $toolbar = $dataList.find('.toolbar'); + var $tierSelect = $('
').addClass('filters tier-select').prependTo($toolbar); + var $tierSelectLabel = $('