diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 7381715d693..e1dd02d4126 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -1766,6 +1766,37 @@ div.list-view td.state.off span { background-position: 100% -431px; } +/*List-view: subselect dropdown*/ +.list-view .subselect { + width: 116px; + display: block; + float: left; + background: url(../images/bg-gradients.png) 0px -42px; + padding: 0; + margin: 8px 0 1px 7px; + clear: both; + border: 1px solid #A8A7A7; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} + +.list-view .subselect span { + margin: 4px 0 0 12px; +} + +.list-view .subselect select { + width: 85%; + margin: 5px 0 4px; + font-size: 10px; +} + +.detail-group .main-groups table td.value .view-all:hover { + background-position: 100% -431px; +} + .panel.always-maximized .detail-group .main-groups table td.value span { width: 565px; } @@ -7743,6 +7774,23 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t margin: 0 22px 0 0; } +/** Fix long table overflow*/ +.detail-view .multi-edit { + width: 100%; +} + +.detail-view .multi-edit table { + width: 97%; + max-width: inherit; +} + +.detail-view .multi-edit table tr th, +.detail-view .multi-edit table tr td { + width: 87px !important; + min-width: 87px !important; + max-width: 87px !important; +} + /** Header fields*/ .multi-edit .header-fields { position: relative; @@ -10561,6 +10609,37 @@ div.ui-dialog div.acl div.multi-edit div.data div.data-body div.data-item table width: 65px; } +/*HEALTH CHECK*/ +.ui-dialog .health-check { + height: 295px !important; + padding-bottom: 93px; +} + +div.ui-dialog div.health-check div.health-check-description { + color: #808080; +} + +div.ui-dialog div.health-check div.form-container form div.form-item { + width: 58% margin-left:116px; + margin-top: -16px; + margin-bottom: 30px; +} + +div.ui-dialog div.health-check div.health-check-config-title { + float: left; + color: #808080; + font-size: 17px; + margin-left: 15px; +} + +div.ui-dialog div.health-check div.health-check-advanced-title { + float: left; + color: #808080; + font-size: 17px; + margin-left: 15px; + margin-top: -70px; +} + /*Autoscaler*/ .ui-dialog div.autoscaler { overflow: auto; diff --git a/ui/index.jsp b/ui/index.jsp index d1e6bfa923b..3b8f37886ef 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -1645,6 +1645,7 @@ under the License. + diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 15ead8cd5a0..65be302c0c9 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -2609,6 +2609,17 @@ action: cloudStack.lbStickyPolicy.dialog() } }, + + 'health-check':{ + label:'Health Check', + custom:{ + requireValidation: true , + buttonLabel:'Configure', + action:cloudStack.uiCustom.healthCheck() + + } + }, + 'autoScale': { label: 'AutoScale', custom: { diff --git a/ui/scripts/ui-custom/healthCheck.js b/ui/scripts/ui-custom/healthCheck.js new file mode 100644 index 00000000000..c4c84e5236b --- /dev/null +++ b/ui/scripts/ui-custom/healthCheck.js @@ -0,0 +1,342 @@ +// 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.healthCheck = function(args) { + + // Place outer args here as local variables + // i.e, -- var dataProvider = args.dataProvider + + return function(args){ + if(args.context.multiRules == undefined) { //LB rule is not created yet + cloudStack.dialog.notice({ message: _l('Health Check can only be configured on a created LB rule') }); + return; + } + + var formData = args.formData; + var forms = $.extend(true, {}, args.forms); + var topFieldForm, bottomFieldForm , $topFieldForm , $bottomFieldForm; + var topfields = forms.topFields; + + var $healthCheckDesc = $('
Your load balancer will automatically perform health checks on your cloudstack instances and only route traffic to instances that pass the health check
').addClass('health-check-description'); + var $healthCheckConfigTitle = $('


Configuration Options :
').addClass('health-check-config-title'); + var $healthCheckAdvancedTitle = $('


Advanced Options :
').addClass('health-check-advanced-title'); + + var $healthCheckDialog = $('
').addClass('health-check'); + $healthCheckDialog.append($healthCheckDesc); + $healthCheckDialog.append($healthCheckConfigTitle); + var $loadingOnDialog = $('
').addClass('loading-overlay'); + + var policyObj = null; + var pingpath1 = '/'; + var responsetimeout1 = '2'; + var healthinterval1 = '5'; + var healthythreshold1 = '2'; + var unhealthythreshold1 = '1'; + + $.ajax({ + url: createURL('listLBHealthCheckPolicies'), + data: { + lbruleid: args.context.multiRules[0].id + }, + async: false, + success: function(json) { + if(json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0] != undefined) { + policyObj = json.listlbhealthcheckpoliciesresponse.healthcheckpolicies[0].healthcheckpolicy[0]; + pingpath1 = policyObj.pingpath; //API bug: API doesn't return it + responsetimeout1 = policyObj.responsetime; + healthinterval1 = policyObj.healthcheckinterval; + healthythreshold1 = policyObj.healthcheckthresshold; + unhealthythreshold1 = policyObj.unhealthcheckthresshold; + } + } + }); + + topFieldForm = cloudStack.dialog.createForm({ + context: args.context, + noDialog: true, // Don't render a dialog, just return $formContainer + form: { + title: '', + fields:{ + pingpath: {label: 'Ping Path', docID:'helpAccountUsername' , validation: {required: false}, defaultValue: pingpath1} + } + } + }); + + $topFieldForm = topFieldForm.$formContainer; + $topFieldForm.appendTo($healthCheckDialog); + + $healthCheckDialog.append($healthCheckAdvancedTitle); + + bottomFieldForm = cloudStack.dialog.createForm ({ + context:args.context, + noDialog:true, + form:{ + title:'', + fields:{ + responsetimeout: {label: 'Response Timeout (in sec)' , validation:{required:false}, defaultValue: responsetimeout1}, + healthinterval: {label: 'Health Check Interval (in sec)', validation:{required:false}, defaultValue: healthinterval1}, + healthythreshold: {label: 'Healthy Threshold', validation: {required:false}, defaultValue: healthythreshold1}, + unhealthythreshold: {label: 'Unhealthy Threshold' , validation: { required:false}, defaultValue: unhealthythreshold1} + } + } + }); + + $bottomFieldForm = bottomFieldForm.$formContainer; + $bottomFieldForm.appendTo($healthCheckDialog); + + + var buttons = [ + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + } + ]; + + if(policyObj == null) { //policy is not created yet + buttons.push( + { + text: _l('Create'), + 'class': 'ok', + click: function() { + $loadingOnDialog.appendTo($healthCheckDialog); + var formData = cloudStack.serializeForm($healthCheckDialog.find('form')); + var data = { + lbruleid: args.context.multiRules[0].id, + pingpath: formData.pingpath, + responsetimeout: formData.responsetimeout, + intervaltime: formData.healthinterval, + healthythreshold: formData.healthythreshold, + unhealthythreshold: formData.unhealthythreshold + }; + + $.ajax({ + url: createURL('createLBHealthCheckPolicy'), + data: data, + success: function(json) { + var jobId = json.createlbhealthcheckpolicyresponse.jobid; + var createLBHealthCheckPolicyIntervalId = setInterval(function(){ + $.ajax({ + url: createURL('queryAsyncJobResult'), + data: { + jobid: jobId + }, + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(createLBHealthCheckPolicyIntervalId); + + if (result.jobstatus == 1) { + cloudStack.dialog.notice({ message: _l('Health Check Policy has been created') }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + else if (result.jobstatus == 2) { + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + } + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + } + ); + } + else { //policy exists already + buttons.push( + //Update Button (begin) - call delete API first, then create API + { + text: _l('Update'), + 'class': 'ok', + click: function() { + $loadingOnDialog.appendTo($healthCheckDialog); + + $.ajax({ + url: createURL('deleteLBHealthCheckPolicy'), + data: { + id : policyObj.id + }, + success: function(json) { + var jobId = json.deletelbhealthcheckpolicyresponse.jobid; + var deleteLBHealthCheckPolicyIntervalId = setInterval(function(){ + $.ajax({ + url: createURL('queryAsyncJobResult'), + data: { + jobid: jobId + }, + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(deleteLBHealthCheckPolicyIntervalId); + + if (result.jobstatus == 1) { + var formData = cloudStack.serializeForm($healthCheckDialog.find('form')); + var data = { + lbruleid: args.context.multiRules[0].id, + pingpath: formData.pingpath, + responsetimeout: formData.responsetimeout, + intervaltime: formData.healthinterval, + healthythreshold: formData.healthythreshold, + unhealthythreshold: formData.unhealthythreshold + }; + + $.ajax({ + url: createURL('createLBHealthCheckPolicy'), + data: data, + success: function(json) { + var jobId = json.createlbhealthcheckpolicyresponse.jobid; + var createLBHealthCheckPolicyIntervalId = setInterval(function(){ + $.ajax({ + url: createURL('queryAsyncJobResult'), + data: { + jobid: jobId + }, + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(createLBHealthCheckPolicyIntervalId); + + if (result.jobstatus == 1) { + cloudStack.dialog.notice({ message: _l('Health Check Policy has been updated') }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + else if (result.jobstatus == 2) { + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + } + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + else if (result.jobstatus == 2) { + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + } + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + } + //Update Button (end) + , + //Delete Button (begin) - call delete API + { + text: _l('Delete'), + 'class': 'delete', + click: function() { + $loadingOnDialog.appendTo($healthCheckDialog); + + $.ajax({ + url: createURL('deleteLBHealthCheckPolicy'), + data: { + id : policyObj.id + }, + success: function(json) { + var jobId = json.deletelbhealthcheckpolicyresponse.jobid; + var deleteLBHealthCheckPolicyIntervalId = setInterval(function(){ + $.ajax({ + url: createURL('queryAsyncJobResult'), + data: { + jobid: jobId + }, + success: function(json) { + var result = json.queryasyncjobresultresponse; + if (result.jobstatus == 0) { + return; //Job has not completed + } + else { + clearInterval(deleteLBHealthCheckPolicyIntervalId); + + if (result.jobstatus == 1) { + cloudStack.dialog.notice({ message: _l('Health Check Policy has been deleted') }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + else if (result.jobstatus == 2) { + cloudStack.dialog.notice({ message: _s(result.jobresult.errortext) }); + $loadingOnDialog.remove(); + $healthCheckDialog.dialog('destroy'); + $('.overlay').remove(); + } + } + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + } + //Delete Button (end) + ); + } + + $healthCheckDialog.dialog({ + title: 'Health Check Wizard', + width: 600, + height: 600, + draggable: true, + closeonEscape: false, + overflow:'auto', + open:function() { + $("button").each(function(){ + $(this).attr("style", "left: 400px; position: relative; margin-right: 5px; "); + }); + + $('.ui-dialog .delete').css('left','140px'); + + }, + buttons: buttons + }).closest('.ui-dialog').overlay(); + + } + } + }(jQuery, cloudStack)); + + diff --git a/ui/scripts/ui/widgets/toolTip.js b/ui/scripts/ui/widgets/toolTip.js index af6c2aa6d3f..6967acc7da0 100644 --- a/ui/scripts/ui/widgets/toolTip.js +++ b/ui/scripts/ui/widgets/toolTip.js @@ -156,7 +156,7 @@ // Fix overlay setTimeout(function() { - $('.tooltip-box').zIndex($(':ui-dialog').zIndex() + 1); }); + $('.tooltip-box').zIndex($(':ui-dialog').zIndex() + 10); }); };