diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 573afe9daf9..7fbc3668733 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -8837,6 +8837,346 @@ div.panel.ui-dialog div.list-view div.fixed-header { background: #DFE1E3; } +/*VPC / vApps*/ +.vpc-chart { + width: 100%; + height: 93%; + overflow: auto; + position: relative; + margin: 30px 0 0; +} + +.vpc-chart .vpc-title { + font-size: 24px; + /*+placement:shift 50px 40px;*/ + position: relative; + left: 50px; + top: 40px; + position: absolute; + color: #5F768A; +} + +.vpc-chart ul.tiers { + padding: 0 0 0 26px; + margin: 79px 0 0 232px; + border-left: 3px solid #CCC; +} + +.vpc-chart li.tier { + display: block; + width: 258px; + height: 107px; + margin: -55px 0 90px; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + border: 1px solid #50545A; + background: url(../images/bg-gradients.png) 0px -2637px; + /*+placement:shift 0px 58px;*/ + position: relative; + left: 0px; + top: 58px; + position: relative; + /*+box-shadow:0px 5px 7px #DADADA;*/ + -moz-box-shadow: 0px 5px 7px #DADADA; + -webkit-box-shadow: 0px 5px 7px #DADADA; + -o-box-shadow: 0px 5px 7px #DADADA; + box-shadow: 0px 5px 7px #DADADA; +} + +.vpc-chart li.tier .loading-overlay { + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} + +.vpc-chart li.tier .connect-line { + position: absolute; + width: 28px; + height: 3px; + background: #CCCCCC 0px -8px; + /*+placement:shift -29px 49px;*/ + position: relative; + left: -29px; + top: 49px; + position: absolute; +} + +.vpc-chart li.tier span.title { + color: #FFFFFF; + /*+placement:shift 11px 13px;*/ + position: relative; + left: 11px; + top: 13px; + position: absolute; + font-size: 24px; + /*+text-shadow:1px 2px 2px #000000;*/ + -moz-text-shadow: 1px 2px 2px #000000; + -webkit-text-shadow: 1px 2px 2px #000000; + -o-text-shadow: 1px 2px 2px #000000; + text-shadow: 1px 2px 2px #000000; +} + +.vpc-chart li.tier span.cidr { + /*+placement:shift 12px 46px;*/ + position: relative; + left: 12px; + top: 46px; + position: absolute; + font-size: 14px; + /*+text-shadow:0px -1px 1px #343E4C;*/ + -moz-text-shadow: 0px -1px 1px #343E4C; + -webkit-text-shadow: 0px -1px 1px #343E4C; + -o-text-shadow: 0px -1px 1px #343E4C; + text-shadow: 0px -1px 1px #343E4C; + color: #FFFFFF; +} + +.vpc-chart li.tier .actions { + width: 258px; + height: 35px; + background: #CCC; + /*+border-radius:0 0 4px 4px;*/ + -moz-border-radius: 0 0 4px 4px; + -webkit-border-radius: 0 0 4px 4px; + -khtml-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; + /*+placement:shift -1px 71px;*/ + position: relative; + left: -1px; + top: 71px; + position: absolute; + /*+box-shadow:inset 0px 1px #FFFFFF;*/ + -moz-box-shadow: inset 0px 1px #FFFFFF; + -webkit-box-shadow: inset 0px 1px #FFFFFF; + -o-box-shadow: inset 0px 1px #FFFFFF; + box-shadow: inset 0px 1px #FFFFFF; + border: 1px solid #808080; + border-top: 1px solid #4C545E; + position: absolute; +} + +.vpc-chart li.tier .actions .action { + cursor: pointer; + float: left; + width: 50px; + height: 24px; + text-align: center; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + margin: 4px 0px 4px 4px; + border: 1px solid #909090; + color: #4B637A; + font-weight: bold; + /*+text-shadow:0px 1px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px 1px #FFFFFF; + -o-text-shadow: 0px 1px 1px #FFFFFF; + text-shadow: 0px 1px 1px #FFFFFF; + background: url(../images/bg-gradients.png) 0px -2533px; +} + +.vpc-chart li.tier .actions .action.disabled, +.vpc-chart li.tier .actions .action.disabled:hover { + color: #9D9D9D; + background: #CFCFCF; + /*+text-shadow:none;*/ + -moz-text-shadow: none; + -webkit-text-shadow: none; + -o-text-shadow: none; + text-shadow: none; + border-color: #B5B5B5; + cursor: not-allowed; + /*+box-shadow:none;*/ + -moz-box-shadow: none; + -webkit-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; +} + +.vpc-chart li.tier .actions .action:hover { + border: 1px solid #7A8B9A; + background-position: 0px -106px; + color: #5B7A96; + /*+box-shadow:inset 1px 2px 4px #808080;*/ + -moz-box-shadow: inset 1px 2px 4px #808080; + -webkit-box-shadow: inset 1px 2px 4px #808080; + -o-box-shadow: inset 1px 2px 4px #808080; + box-shadow: inset 1px 2px 4px #808080; +} + +.vpc-chart li.tier .actions .action span.label { + /*+placement:shift 1px 3px;*/ + position: relative; + left: 1px; + top: 3px; + font-size: 11px; +} + +.vpc-chart li.tier .actions .action.remove, +.vpc-chart li.tier .actions .action.remove:hover { + background: none; + width: 30px; + padding: 0; + float: right; + border: none; + /*+placement:shift -3px -2px;*/ + position: relative; + left: -3px; + top: -2px; + /*+box-shadow:none;*/ + -moz-box-shadow: none; + -webkit-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; +} + +.vpc-chart li.tier .action span.icon { + background-image: url(../images/sprites.png); + cursor: pointer; + width: 37px; + height: 23px; + float: left; + /*+placement:shift 1px 3px;*/ + position: relative; + left: 1px; + top: 3px; +} + +.vpc-chart li.tier .vm-count { + font-size: 23px; + left: 134px; + top: 3px; + position: absolute; + color: #FFFFFF; + /*+text-shadow:1px 2px 2px #000000;*/ + -moz-text-shadow: 1px 2px 2px #000000; + -webkit-text-shadow: 1px 2px 2px #000000; + -o-text-shadow: 1px 2px 2px #000000; + text-shadow: 1px 2px 2px #000000; + cursor: pointer; + display: block; + padding: 5px; + text-align: center; + width: 100px; + border: 1px solid transparent; + margin: 4px; +} + +.vpc-chart li.tier .vm-count:hover { + border-radius: 4px; + border: 1px solid #4C545E; + background: url(../images/bg-gradients.png) 0px -2751px; +} + +.vpc-chart li.tier .vm-count .total { + padding-right: 4px; + font-size: 24px; +} + +.vpc-chart li.tier.placeholder { + background: #ECECEC; + border: dotted #ACACAC; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + /*+box-shadow:none;*/ + -moz-box-shadow: none; + -webkit-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; + cursor: pointer; +} + +.vpc-chart li.tier.placeholder:hover { + background: #D3D3D3; + /*+box-shadow:0px 2px 8px #A7A7A7;*/ + -moz-box-shadow: 0px 2px 8px #A7A7A7; + -webkit-box-shadow: 0px 2px 8px #A7A7A7; + -o-box-shadow: 0px 2px 8px #A7A7A7; + box-shadow: 0px 2px 8px #A7A7A7; +} + +.vpc-chart li.tier.placeholder span { + top: 40px; + left: 66px; + color: #9F9F9F; + /*+text-shadow:none;*/ + -moz-text-shadow: none; + -webkit-text-shadow: none; + -o-text-shadow: none; + text-shadow: none; +} + +.vpc-chart li.tier.placeholder:hover span { + color: #000000; + /*+text-shadow:0px 0px 7px #FFFFFF;*/ + -moz-text-shadow: 0px 0px 7px #FFFFFF; + -webkit-text-shadow: 0px 0px 7px #FFFFFF; + -o-text-shadow: 0px 0px 7px #FFFFFF; + text-shadow: 0px 0px 7px #FFFFFF; +} + +.vpc-chart li.tier.virtual-router { + margin: 0px; + width: 222px; + height: 65px; + /*+placement:shift 17px -36px;*/ + position: relative; + left: 17px; + top: -36px; + background-position: 0px -2519px; + border: 1px solid #ADADAD; +} + +.vpc-chart li.tier.virtual-router span { + color: #586E82; + font-size: 18px; + /*+text-shadow:0px 1px 3px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 3px #FFFFFF; + -webkit-text-shadow: 0px 1px 3px #FFFFFF; + -o-text-shadow: 0px 1px 3px #FFFFFF; + text-shadow: 0px 1px 3px #FFFFFF; + /*+placement:shift 53px 22px;*/ + position: relative; + left: 53px; + top: 22px; +} + +.vpc-chart li.tier.virtual-router .connect-line { + /*+placement:shift -47px 14px;*/ + position: relative; + left: -47px; + top: 14px; + width: 46px; +} + +/*Configure ACL dialog*/ +.ui-dialog.configure-acl { +} + +.ui-dialog.configure-acl .ui-dialog-buttonpane { + /*+placement:shift 709px -2px;*/ + position: relative; + left: 709px; + top: -2px; +} + +.ui-dialog.configure-acl .multi-edit .data { + width: 807px; + height: 370px; + overflow: auto; +} + /*Action icons*/ .action.edit .icon { background-position: 1px -1px; @@ -9005,13 +9345,15 @@ div.panel.ui-dialog div.list-view div.fixed-header { .create .icon, .createTemplate .icon, -.enableSwift .icon { +.enableSwift .icon, +.addVM .icon { background-position: -69px -63px; } .create:hover .icon, .createTemplate:hover .icon, -.enableSwift:hover .icon { +.enableSwift:hover .icon, +.addVM:hover .icon { background-position: -69px -645px; } @@ -9073,11 +9415,13 @@ div.panel.ui-dialog div.list-view div.fixed-header { background-position: -167px -648px; } -.generateKeys .icon { +.generateKeys .icon, +.networkACL .icon { background-position: -167px -95px; } -.generateKeys:hover .icon { +.generateKeys:hover .icon, +.networkACL:hover .icon { background-position: -167px -677px; } diff --git a/ui/images/bg-gradients.png b/ui/images/bg-gradients.png index 2ef74540bbf..52016f0cf48 100644 Binary files a/ui/images/bg-gradients.png and b/ui/images/bg-gradients.png differ diff --git a/ui/index.jsp b/ui/index.jsp index 3c377eaef02..fb3327f5466 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -1629,11 +1629,14 @@ + + + diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js new file mode 100644 index 00000000000..8559477573d --- /dev/null +++ b/ui/scripts/instanceWizard.js @@ -0,0 +1,513 @@ +(function($, cloudStack) { + var zoneObjs, hypervisorObjs, featuredTemplateObjs, communityTemplateObjs, myTemplateObjs, featuredIsoObjs, community + var selectedZoneObj, selectedTemplateObj, selectedHypervisor, selectedDiskOfferingObj; + var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group' + + cloudStack.instanceWizard = { + maxDiskOfferingSize: function() { + return g_capabilities.customdiskofferingmaxsize; + }, + steps: [ + // Step 1: Setup + function(args) { + $.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) { + 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) { + 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) { + 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) { + featuredIsoObjs = json.listisosresponse.iso; + } + }); + $.ajax({ + url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"), + dataType: "json", + async: false, + success: function(json) { + communityIsoObjs = json.listisosresponse.iso; + } + }); + $.ajax({ + url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"), + dataType: "json", + async: false, + success: function(json) { + 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 + } + } + 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(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(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. + step5ContainerType = 'select-network'; + } + 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') { + var defaultNetworkArray = [], optionalNetworkArray = []; + var networkData = { + zoneId: args.currentData.zoneid + }; + + if (!(cloudStack.context.projects && cloudStack.context.projects[0])) { + networkData.domainid = g_domainid; + networkData.account = g_account; + } + + var networkObjs; + $.ajax({ + url: createURL('listNetworks'), + data: networkData, + dataType: "json", + async: false, + success: function(json) { + networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : []; + } + }); + + + var apiCmd = "listNetworkOfferings&guestiptype=Isolated&supportedServices=sourceNat&state=Enabled&specifyvlan=false&zoneid=" + args.currentData.zoneid ; + var array1 = []; + var guestTrafficTypeTotal = 0; + + $.ajax({ + url: createURL(apiCmd + array1.join("")), //get the network offering for isolated network with sourceNat + dataType: "json", + async: false, + success: function(json) { + networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; + } + }); + //get network offerings (end) *** + + + args.response.success({ + type: 'select-network', + data: { + myNetworks: [], //not used any more + sharedNetworks: networkObjs, + securityGroups: [], + networkOfferings: networkOfferingObjs + } + }); + } + + 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++) { + if(items[i].name != "default") //exclude default security group because it is always applied + securityGroupArray.push(items[i]); + } + } + } + }); + args.response.success({ + type: 'select-security-group', + data: { + myNetworks: [], //not used any more + sharedNetworks: [], + securityGroups: securityGroupArray, + networkOfferings: [] + } + }); + } + + else if(step5ContainerType == 'nothing-to-select') { + args.response.success({ + type: 'nothing-to-select', + data: { + myNetworks: [], //not used any more + sharedNetworks: [], + securityGroups: [], + networkOfferings: [] + } + }); + } + + }, + + // Step 6: Review + function(args) { + return false; + } + ], + action: function(args) { +/* +var isValid = true; +isValid &= validateString("Name", $thisPopup.find("#wizard_vm_name"), $thisPopup.find("#wizard_vm_name_errormsg"), true); //optional +isValid &= validateString("Group", $thisPopup.find("#wizard_vm_group"), $thisPopup.find("#wizard_vm_group_errormsg"), true); //optional +if (!isValid) +return; +*/ + + // Create a new VM!!!! + var array1 = []; + + //step 1 : select zone + array1.push("&zoneId=" + args.data.zoneid); + + //step 2: select template + array1.push("&templateId=" + args.data.templateid); + array1.push("&hypervisor=" + selectedHypervisor); + + //step 3: select service offering + array1.push("&serviceOfferingId=" + args.data.serviceofferingid); + + //step 4: select disk offering + if(args.data.diskofferingid != null && args.data.diskofferingid != "0") { + array1.push("&diskOfferingId=" + args.data.diskofferingid); + if(selectedDiskOfferingObj.iscustomized == true) + array1.push("&size=" + args.data.size); + } + + //step 5: select network + if (step5ContainerType == 'select-network') { + var array2 = []; + var defaultNetworkId = args.data.defaultNetwork; //args.data.defaultNetwork might be equal to string "new-network" or a network ID + + var checkedNetworkIdArray; + if(typeof(args.data["my-networks"]) == "object" && args.data["my-networks"].length != null) { //args.data["my-networks"] is an array of string, e.g. ["203", "202"], + checkedNetworkIdArray = args.data["my-networks"]; + } + else if(typeof(args.data["my-networks"]) == "string" && args.data["my-networks"].length > 0) { //args.data["my-networks"] is a string, e.g. "202" + checkedNetworkIdArray = []; + checkedNetworkIdArray.push(args.data["my-networks"]); + } + else { // typeof(args.data["my-networks"]) == null + checkedNetworkIdArray = []; + } + + //create new network starts here + if(args.data["new-network"] == "create-new-network") { + var isCreateNetworkSuccessful = true; + $.ajax({ + url: createURL("createNetwork&networkOfferingId="+args.data["new-network-networkofferingid"]+"&name="+todb(args.data["new-network-name"])+"&displayText="+todb(args.data["new-network-name"])+"&zoneId="+selectedZoneObj.id), + dataType: "json", + async: false, + success: function(json) { + newNetwork = json.createnetworkresponse.network; + checkedNetworkIdArray.push(newNetwork.id); + if(defaultNetworkId == "new-network") + defaultNetworkId = newNetwork.id; + }, + error: function(XMLHttpResponse) { + isCreateNetworkSuccessful = false; + var errorMsg = "Failed to create new network, unable to proceed to deploy VM. Error: " + parseXMLHttpResponse(XMLHttpResponse); + //alert(errorMsg); + args.response.error(errorMsg); //args.response.error(errorMsg) here doesn't show errorMsg. Waiting for Brian to fix it. use alert(errorMsg) to show errorMsg for now. + } + }); + if(isCreateNetworkSuccessful == false) + return; + } + //create new network ends here + + //add default network first + if(defaultNetworkId != null && defaultNetworkId.length > 0) + array2.push(defaultNetworkId); + + //then, add other checked networks + if(checkedNetworkIdArray.length > 0) { + for(var i=0; i < checkedNetworkIdArray.length; i++) { + if(checkedNetworkIdArray[i] != defaultNetworkId) //exclude defaultNetworkId that has been added to array2 + array2.push(checkedNetworkIdArray[i]); + } + } + + array1.push("&networkIds=" + array2.join(",")); + } + else if (step5ContainerType == 'select-security-group') { + var checkedSecurityGroupIdArray; + if(typeof(args.data["security-groups"]) == "object" && args.data["security-groups"].length != null) { //args.data["security-groups"] is an array of string, e.g. ["2375f8cc-8a73-4b8d-9b26-50885a25ffe0", "27c60d2a-de7f-4bb7-96e5-a602cec681df","c6301d77-99b5-4e8a-85e2-3ea2ab31c342"], + checkedSecurityGroupIdArray = args.data["security-groups"]; + } + else if(typeof(args.data["security-groups"]) == "string" && args.data["security-groups"].length > 0) { //args.data["security-groups"] is a string, e.g. "2375f8cc-8a73-4b8d-9b26-50885a25ffe0" + checkedSecurityGroupIdArray = []; + checkedSecurityGroupIdArray.push(args.data["security-groups"]); + } + else { // typeof(args.data["security-groups"]) == null + checkedSecurityGroupIdArray = []; + } + + if(checkedSecurityGroupIdArray.length > 0) + array1.push("&securitygroupids=" + checkedSecurityGroupIdArray.join(",")); + } + + var displayname = args.data.displayname; + if(displayname != null && displayname.length > 0) { + array1.push("&displayname="+todb(displayname)); + array1.push("&name="+todb(displayname)); + } + + var group = args.data.groupname; + if (group != null && group.length > 0) + array1.push("&group="+todb(group)); + + //array1.push("&startVm=false"); //for testing only, comment it out before checking in + + $.ajax({ + url: createURL("deployVirtualMachine"+array1.join("")), + dataType: "json", + success: function(json) { + var jid = json.deployvirtualmachineresponse.jobid; + 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 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) { + args.response.error(parseXMLHttpResponse(XMLHttpResponse)); //wait for Brian to implement + } + }); + } + }; +}(jQuery, cloudStack)); diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 77688c978a6..5e9b3f3bb32 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -15,11 +15,6 @@ // specific language governing permissions and limitations // under the License. (function($, cloudStack) { - - var zoneObjs, hypervisorObjs, featuredTemplateObjs, communityTemplateObjs, myTemplateObjs, featuredIsoObjs, communityIsoObjs, myIsoObjs, serviceOfferingObjs, diskOfferingObjs, networkOfferingObjs, physicalNetworkObjs; - var selectedZoneObj, selectedTemplateObj, selectedHypervisor, selectedDiskOfferingObj; - var step5ContainerType = 'nothing-to-select'; //'nothing-to-select', 'select-network', 'select-security-group' - cloudStack.sections.instances = { title: 'label.instances', id: 'instances', @@ -69,513 +64,7 @@ label: 'label.vm.add', action: { - custom: cloudStack.instanceWizard({ - maxDiskOfferingSize: function() { - return g_capabilities.customdiskofferingmaxsize; - }, - steps: [ - // Step 1: Setup - function(args) { - $.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) { - 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) { - 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) { - 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) { - featuredIsoObjs = json.listisosresponse.iso; - } - }); - $.ajax({ - url: createURL("listIsos&isofilter=community&zoneid=" + args.currentData.zoneid + "&bootable=true"), - dataType: "json", - async: false, - success: function(json) { - communityIsoObjs = json.listisosresponse.iso; - } - }); - $.ajax({ - url: createURL("listIsos&isofilter=selfexecutable&zoneid=" + args.currentData.zoneid + "&bootable=true"), - dataType: "json", - async: false, - success: function(json) { - 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 - } - } - 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(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(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. - step5ContainerType = 'select-network'; - } - 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') { - var defaultNetworkArray = [], optionalNetworkArray = []; - var networkData = { - zoneId: args.currentData.zoneid - }; - - if (!(cloudStack.context.projects && cloudStack.context.projects[0])) { - networkData.domainid = g_domainid; - networkData.account = g_account; - } - - var networkObjs; - $.ajax({ - url: createURL('listNetworks'), - data: networkData, - dataType: "json", - async: false, - success: function(json) { - networkObjs = json.listnetworksresponse.network ? json.listnetworksresponse.network : []; - } - }); - - - var apiCmd = "listNetworkOfferings&guestiptype=Isolated&supportedServices=sourceNat&state=Enabled&specifyvlan=false&zoneid=" + args.currentData.zoneid ; - var array1 = []; - var guestTrafficTypeTotal = 0; - - $.ajax({ - url: createURL(apiCmd + array1.join("")), //get the network offering for isolated network with sourceNat - dataType: "json", - async: false, - success: function(json) { - networkOfferingObjs = json.listnetworkofferingsresponse.networkoffering; - } - }); - //get network offerings (end) *** - - - args.response.success({ - type: 'select-network', - data: { - myNetworks: [], //not used any more - sharedNetworks: networkObjs, - securityGroups: [], - networkOfferings: networkOfferingObjs - } - }); - } - - 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++) { - if(items[i].name != "default") //exclude default security group because it is always applied - securityGroupArray.push(items[i]); - } - } - } - }); - args.response.success({ - type: 'select-security-group', - data: { - myNetworks: [], //not used any more - sharedNetworks: [], - securityGroups: securityGroupArray, - networkOfferings: [] - } - }); - } - - else if(step5ContainerType == 'nothing-to-select') { - args.response.success({ - type: 'nothing-to-select', - data: { - myNetworks: [], //not used any more - sharedNetworks: [], - securityGroups: [], - networkOfferings: [] - } - }); - } - - }, - - // Step 6: Review - function(args) { - return false; - } - ], - action: function(args) { - /* - var isValid = true; - isValid &= validateString("Name", $thisPopup.find("#wizard_vm_name"), $thisPopup.find("#wizard_vm_name_errormsg"), true); //optional - isValid &= validateString("Group", $thisPopup.find("#wizard_vm_group"), $thisPopup.find("#wizard_vm_group_errormsg"), true); //optional - if (!isValid) - return; - */ - - // Create a new VM!!!! - var array1 = []; - - //step 1 : select zone - array1.push("&zoneId=" + args.data.zoneid); - - //step 2: select template - array1.push("&templateId=" + args.data.templateid); - array1.push("&hypervisor=" + selectedHypervisor); - - //step 3: select service offering - array1.push("&serviceOfferingId=" + args.data.serviceofferingid); - - //step 4: select disk offering - if(args.data.diskofferingid != null && args.data.diskofferingid != "0") { - array1.push("&diskOfferingId=" + args.data.diskofferingid); - if(selectedDiskOfferingObj.iscustomized == true) - array1.push("&size=" + args.data.size); - } - - //step 5: select network - if (step5ContainerType == 'select-network') { - var array2 = []; - var defaultNetworkId = args.data.defaultNetwork; //args.data.defaultNetwork might be equal to string "new-network" or a network ID - - var checkedNetworkIdArray; - if(typeof(args.data["my-networks"]) == "object" && args.data["my-networks"].length != null) { //args.data["my-networks"] is an array of string, e.g. ["203", "202"], - checkedNetworkIdArray = args.data["my-networks"]; - } - else if(typeof(args.data["my-networks"]) == "string" && args.data["my-networks"].length > 0) { //args.data["my-networks"] is a string, e.g. "202" - checkedNetworkIdArray = []; - checkedNetworkIdArray.push(args.data["my-networks"]); - } - else { // typeof(args.data["my-networks"]) == null - checkedNetworkIdArray = []; - } - - //create new network starts here - if(args.data["new-network"] == "create-new-network") { - var isCreateNetworkSuccessful = true; - $.ajax({ - url: createURL("createNetwork&networkOfferingId="+args.data["new-network-networkofferingid"]+"&name="+todb(args.data["new-network-name"])+"&displayText="+todb(args.data["new-network-name"])+"&zoneId="+selectedZoneObj.id), - dataType: "json", - async: false, - success: function(json) { - newNetwork = json.createnetworkresponse.network; - checkedNetworkIdArray.push(newNetwork.id); - if(defaultNetworkId == "new-network") - defaultNetworkId = newNetwork.id; - }, - error: function(XMLHttpResponse) { - isCreateNetworkSuccessful = false; - var errorMsg = "Failed to create new network, unable to proceed to deploy VM. Error: " + parseXMLHttpResponse(XMLHttpResponse); - //alert(errorMsg); - args.response.error(errorMsg); //args.response.error(errorMsg) here doesn't show errorMsg. Waiting for Brian to fix it. use alert(errorMsg) to show errorMsg for now. - } - }); - if(isCreateNetworkSuccessful == false) - return; - } - //create new network ends here - - //add default network first - if(defaultNetworkId != null && defaultNetworkId.length > 0) - array2.push(defaultNetworkId); - - //then, add other checked networks - if(checkedNetworkIdArray.length > 0) { - for(var i=0; i < checkedNetworkIdArray.length; i++) { - if(checkedNetworkIdArray[i] != defaultNetworkId) //exclude defaultNetworkId that has been added to array2 - array2.push(checkedNetworkIdArray[i]); - } - } - - array1.push("&networkIds=" + array2.join(",")); - } - else if (step5ContainerType == 'select-security-group') { - var checkedSecurityGroupIdArray; - if(typeof(args.data["security-groups"]) == "object" && args.data["security-groups"].length != null) { //args.data["security-groups"] is an array of string, e.g. ["2375f8cc-8a73-4b8d-9b26-50885a25ffe0", "27c60d2a-de7f-4bb7-96e5-a602cec681df","c6301d77-99b5-4e8a-85e2-3ea2ab31c342"], - checkedSecurityGroupIdArray = args.data["security-groups"]; - } - else if(typeof(args.data["security-groups"]) == "string" && args.data["security-groups"].length > 0) { //args.data["security-groups"] is a string, e.g. "2375f8cc-8a73-4b8d-9b26-50885a25ffe0" - checkedSecurityGroupIdArray = []; - checkedSecurityGroupIdArray.push(args.data["security-groups"]); - } - else { // typeof(args.data["security-groups"]) == null - checkedSecurityGroupIdArray = []; - } - - if(checkedSecurityGroupIdArray.length > 0) - array1.push("&securitygroupids=" + checkedSecurityGroupIdArray.join(",")); - } - - var displayname = args.data.displayname; - if(displayname != null && displayname.length > 0) { - array1.push("&displayname="+todb(displayname)); - array1.push("&name="+todb(displayname)); - } - - var group = args.data.groupname; - if (group != null && group.length > 0) - array1.push("&group="+todb(group)); - - //array1.push("&startVm=false"); //for testing only, comment it out before checking in - - $.ajax({ - url: createURL("deployVirtualMachine"+array1.join("")), - dataType: "json", - success: function(json) { - var jid = json.deployvirtualmachineresponse.jobid; - 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 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) { - args.response.error(parseXMLHttpResponse(XMLHttpResponse)); //wait for Brian to implement - } - }); - } - }) + custom: cloudStack.uiCustom.instanceWizard(cloudStack.instanceWizard) }, messages: { diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 597186ee257..150ade27846 100644 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -177,7 +177,7 @@ } }); - var sectionsToShow = ['networks']; + var sectionsToShow = ['networks', 'vpc']; if(havingSecurityGroupNetwork == true) sectionsToShow.push('securityGroups'); @@ -3105,6 +3105,91 @@ } } } + }, + vpc: { + type: 'select', + title: 'VPC', + id: 'vpc', + listView: { + id: 'vpc', + label: 'VPC', + fields: { + name: { label: 'Name' }, + zone: { label: 'Zone' }, + cidr: { label: 'CIDR' } + }, + dataProvider: function(args) { + args.response.success({ + data: [ + { + name: 'VPC 1', + zone: 'San Jose', + cidr: '0.0.0.0/0', + networkdomain: 'testdomain', + accountdomain: 'testdomain' + }, + { + name: 'VPC 2', + zone: 'San Jose', + cidr: '0.0.0.0/0', + networkdomain: 'testdomain', + accountdomain: 'testdomain' + }, + { + name: 'VPC 3', + zone: 'Cupertino', + cidr: '0.0.0.0/0', + networkdomain: 'testdomain', + accountdomain: 'testdomain' + }, + { + name: 'VPC 4', + zone: 'San Jose', + cidr: '0.0.0.0/0', + networkdomain: 'testdomain', + accountdomain: 'testdomain' + } + ] + }); + }, + actions: { + add: { + label: 'Add VPC', + createForm: { + title: 'Add new VPC', + fields: { + name: { label: 'Name', validation: { required: true } }, + zone: { + label: 'Zone', + validation: { required: true }, + select: function(args) { + args.response.success({ + data: [ + { id: 'zone1', description: 'Zone 1' }, + { id: 'zone2', description: 'Zone 2' }, + { id: 'zone3', description: 'Zone 3' } + ] + }); + } + } + } + }, + messages: { + notification: function(args) { return 'Add new VPC'; } + }, + action: function(args) { + args.response.success(); + }, + notification: { poll: function(args) { args.complete(); } } + }, + editVpc: { + label: 'Edit VPC', + action: { + custom: cloudStack.uiCustom.vpc(cloudStack.vpc) + } + } + } + } } } }; diff --git a/ui/scripts/ui-custom/instanceWizard.js b/ui/scripts/ui-custom/instanceWizard.js index 4c1d7911eb4..0dfcdf9d698 100644 --- a/ui/scripts/ui-custom/instanceWizard.js +++ b/ui/scripts/ui-custom/instanceWizard.js @@ -18,7 +18,7 @@ /** * Instance wizard */ - cloudStack.instanceWizard = function(args) { + cloudStack.uiCustom.instanceWizard = function(args) { return function(listViewArgs) { var context = listViewArgs.context; diff --git a/ui/scripts/ui-custom/vpc.js b/ui/scripts/ui-custom/vpc.js new file mode 100644 index 00000000000..3804386c656 --- /dev/null +++ b/ui/scripts/ui-custom/vpc.js @@ -0,0 +1,404 @@ +(function($, cloudStack) { + var elems = { + router: function() { + var $router = $('