diff --git a/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigAnswer.java b/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigAnswer.java new file mode 100644 index 00000000000..dfca4ab5908 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigAnswer.java @@ -0,0 +1,42 @@ +// 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. +package com.cloud.agent.api.routing; + +import java.util.List; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.LoadBalancerTO; +import com.cloud.agent.api.to.NicTO; + +/** + * LoadBalancerConfigCommand sends the load balancer configuration + */ +public class HealthCheckLBConfigAnswer extends Answer { + List loadBalancers; + + protected HealthCheckLBConfigAnswer() { + } + + public HealthCheckLBConfigAnswer(List loadBalancers) { + this.loadBalancers = loadBalancers; + } + + public List getLoadBalancers() { + return loadBalancers; + } + +} diff --git a/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java b/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java new file mode 100644 index 00000000000..f705f6c9707 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/HealthCheckLBConfigCommand.java @@ -0,0 +1,39 @@ +// 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. +package com.cloud.agent.api.routing; + +import com.cloud.agent.api.to.LoadBalancerTO; +import com.cloud.agent.api.to.NicTO; + +/** + * LoadBalancerConfigCommand sends the load balancer configuration + */ +public class HealthCheckLBConfigCommand extends NetworkElementCommand { + LoadBalancerTO[] loadBalancers; + + protected HealthCheckLBConfigCommand() { + } + + public HealthCheckLBConfigCommand(LoadBalancerTO[] loadBalancers) { + this.loadBalancers = loadBalancers; + } + + public LoadBalancerTO[] getLoadBalancers() { + return loadBalancers; + } + +} diff --git a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java index 2d166ea1e1e..df2f8a87490 100644 --- a/api/src/com/cloud/agent/api/to/LoadBalancerTO.java +++ b/api/src/com/cloud/agent/api/to/LoadBalancerTO.java @@ -31,6 +31,7 @@ import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmGroup; import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmProfile; import com.cloud.network.lb.LoadBalancingRule.LbCondition; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.utils.Pair; @@ -46,8 +47,10 @@ public class LoadBalancerTO { boolean inline; DestinationTO[] destinations; private StickinessPolicyTO[] stickinessPolicies; + private HealthCheckPolicyTO[] healthCheckPolicies; private AutoScaleVmGroupTO autoScaleVmGroupTO; final static int MAX_STICKINESS_POLICIES = 1; + final static int MAX_HEALTHCHECK_POLICIES = 1; public LoadBalancerTO(String uuid, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, boolean alreadyAdded, boolean inline, List destinations) { if (destinations == null) { // for autoscaleconfig destinations will be null; @@ -69,23 +72,52 @@ public class LoadBalancerTO { } } - public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, boolean alreadyAdded, boolean inline, List arg_destinations, List stickinessPolicies) { + public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, + boolean alreadyAdded, boolean inline, List arg_destinations, + List stickinessPolicies) { + + this(id, srcIp, srcPort, protocol, algorithm, revoked, alreadyAdded, inline, arg_destinations, + stickinessPolicies, null); + } + + public LoadBalancerTO(String id, String srcIp, int srcPort, String protocol, String algorithm, boolean revoked, + boolean alreadyAdded, boolean inline, List arg_destinations, + List stickinessPolicies, List healthCheckPolicies) { this(id, srcIp, srcPort, protocol, algorithm, revoked, alreadyAdded, inline, arg_destinations); this.stickinessPolicies = null; + this.healthCheckPolicies = null; if (stickinessPolicies != null && stickinessPolicies.size() > 0) { this.stickinessPolicies = new StickinessPolicyTO[MAX_STICKINESS_POLICIES]; int index = 0; for (LbStickinessPolicy stickinesspolicy : stickinessPolicies) { if (!stickinesspolicy.isRevoked()) { - this.stickinessPolicies[index] = new StickinessPolicyTO(stickinesspolicy.getMethodName(), stickinesspolicy.getParams()); + this.stickinessPolicies[index] = new StickinessPolicyTO(stickinesspolicy.getMethodName(), + stickinesspolicy.getParams()); index++; - if (index == MAX_STICKINESS_POLICIES) break; - } + if (index == MAX_STICKINESS_POLICIES) + break; } - if (index == 0) this.stickinessPolicies = null; } + if (index == 0) + this.stickinessPolicies = null; + } + + if (healthCheckPolicies != null && healthCheckPolicies.size() > 0) { + this.healthCheckPolicies = new HealthCheckPolicyTO[MAX_HEALTHCHECK_POLICIES]; + int index = 0; + for (LbHealthCheckPolicy hcp : healthCheckPolicies) { + this.healthCheckPolicies[0] = new HealthCheckPolicyTO(hcp.getpingpath(), hcp.getDescription(), + hcp.getResponseTime(), hcp.getHealthcheckInterval(), hcp.getHealthcheckThresshold(), + hcp.getUnhealthThresshold(), hcp.isRevoked()); + index++; + if (index == MAX_HEALTHCHECK_POLICIES) + break; } + if (index == 0) + this.healthCheckPolicies = null; + } + } protected LoadBalancerTO() { } @@ -126,6 +158,10 @@ public class LoadBalancerTO { return stickinessPolicies; } + public HealthCheckPolicyTO[] getHealthCheckPolicies() { + return healthCheckPolicies; + } + public DestinationTO[] getDestinations() { return destinations; } @@ -158,6 +194,65 @@ public class LoadBalancerTO { this._methodName = methodName; this._paramsList = paramsList; } + } + + public static class HealthCheckPolicyTO { + private String pingPath; + private String description; + private int responseTime; + private int healthcheckInterval; + private int healthcheckThresshold; + private int unhealthThresshold; + private boolean revoke = false; + + public HealthCheckPolicyTO(String pingPath, String description, int responseTime, int healthcheckInterval, + int healthcheckThresshold, int unhealthThresshold, boolean revoke) { + + this.description = description; + this.pingPath = pingPath; + this.responseTime = responseTime; + this.healthcheckInterval = healthcheckInterval; + this.healthcheckThresshold = healthcheckThresshold; + this.unhealthThresshold = unhealthThresshold; + this.revoke = revoke; + } + + public HealthCheckPolicyTO() { + + } + + public String getpingPath() { + return pingPath; + } + + public String getDescription() { + return description; + } + + public int getResponseTime() { + return responseTime; + } + + public int getHealthcheckInterval() { + return healthcheckInterval; + } + + public int getHealthcheckThresshold() { + return healthcheckThresshold; + } + + public int getUnhealthThresshold() { + return unhealthThresshold; + } + + public void setRevoke(boolean revoke) { + this.revoke = revoke; + } + + public boolean isRevoked() { + return revoke; + } + } public static class DestinationTO { @@ -165,6 +260,7 @@ public class LoadBalancerTO { int destPort; boolean revoked; boolean alreadyAdded; + String monitorState; public DestinationTO(String destIp, int destPort, boolean revoked, boolean alreadyAdded) { this.destIp = destIp; this.destPort = destPort; @@ -190,6 +286,14 @@ public class LoadBalancerTO { public boolean isAlreadyAdded() { return alreadyAdded; } + + public void setMonitorState(String state) { + this.monitorState = state; + } + + public String getMonitorState() { + return monitorState; + } } public static class CounterTO implements Serializable { private final String name; diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 0087edca743..f38865c9e34 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -110,6 +110,8 @@ public class EventTypes { public static final String EVENT_LOAD_BALANCER_DELETE = "LB.DELETE"; public static final String EVENT_LB_STICKINESSPOLICY_CREATE = "LB.STICKINESSPOLICY.CREATE"; public static final String EVENT_LB_STICKINESSPOLICY_DELETE = "LB.STICKINESSPOLICY.DELETE"; + public static final String EVENT_LB_HEALTHCHECKPOLICY_CREATE = "LB.HEALTHCHECKPOLICY.CREATE"; + public static final String EVENT_LB_HEALTHCHECKPOLICY_DELETE = "LB.HEALTHCHECKPOLICY.DELETE"; public static final String EVENT_LOAD_BALANCER_UPDATE = "LB.UPDATE"; // Account events diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index efed5cd4f8b..89dac686d0f 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -188,6 +188,7 @@ public interface Network extends ControlledEntity, StateObject, I public static final Capability InlineMode = new Capability("InlineMode"); public static final Capability SupportedTrafficDirection = new Capability("SupportedTrafficDirection"); public static final Capability SupportedEgressProtocols = new Capability("SupportedEgressProtocols"); + public static final Capability HealthCheckPolicy = new Capability("HealthCheckPolicy"); private String name; diff --git a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java index 879ea0ed663..cb3155f9c05 100644 --- a/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java +++ b/api/src/com/cloud/network/element/LoadBalancingServiceProvider.java @@ -18,6 +18,7 @@ package com.cloud.network.element; import java.util.List; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.lb.LoadBalancingRule; @@ -25,6 +26,7 @@ import com.cloud.network.lb.LoadBalancingRule; public interface LoadBalancingServiceProvider extends NetworkElement, IpDeployingRequester { /** * Apply rules + * * @param network * @param rules * @return @@ -34,10 +36,14 @@ public interface LoadBalancingServiceProvider extends NetworkElement, IpDeployin /** * Validate rules + * * @param network * @param rule - * @return true/false. true should be return if there are no validations. false should be return if any oneof the validation fails. + * @return true/false. true should be return if there are no validations. + *false should be return if any oneof the validation fails. * @throws */ boolean validateLBRule(Network network, LoadBalancingRule rule); + + List updateHealthChecks(Network network, List lbrules); } diff --git a/api/src/com/cloud/network/lb/LoadBalancingRule.java b/api/src/com/cloud/network/lb/LoadBalancingRule.java index fb1d988a4de..84526c5ea45 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRule.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRule.java @@ -32,11 +32,14 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { private List destinations; private List stickinessPolicies; private LbAutoScaleVmGroup autoScaleVmGroup; + private List healthCheckPolicies; - public LoadBalancingRule(LoadBalancer lb, List destinations, List stickinessPolicies) { + public LoadBalancingRule(LoadBalancer lb, List destinations, + List stickinessPolicies, List healthCheckPolicies) { this.lb = lb; this.destinations = destinations; this.stickinessPolicies = stickinessPolicies; + this.healthCheckPolicies = healthCheckPolicies; } @Override @@ -136,11 +139,17 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { return stickinessPolicies; } + public List getHealthCheckPolicies() { + return healthCheckPolicies; + } public interface Destination { String getIpAddress(); + int getDestinationPortStart(); + int getDestinationPortEnd(); + boolean isRevoked(); } @@ -174,6 +183,64 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { } } + public static class LbHealthCheckPolicy { + private String pingpath; + private String description; + private int responseTime; + private int healthcheckInterval; + private int healthcheckThresshold; + private int unhealthThresshold; + private boolean _revoke; + + public LbHealthCheckPolicy(String pingpath, String description, int responseTime, int healthcheckInterval, + int healthcheckThresshold, int unhealthThresshold) { + this(pingpath, description, responseTime, healthcheckInterval, healthcheckThresshold, unhealthThresshold, false); + } + + public LbHealthCheckPolicy(String pingpath, String description, int responseTime, int healthcheckInterval, + int healthcheckThresshold, int unhealthThresshold, boolean revoke) { + this.pingpath = pingpath; + this.description = description; + this.responseTime = responseTime; + this.healthcheckInterval = healthcheckInterval; + this.healthcheckThresshold = healthcheckThresshold; + this.unhealthThresshold = unhealthThresshold; + this._revoke = revoke; + } + + public LbHealthCheckPolicy() { + } + + public String getpingpath() { + return pingpath; + } + + public String getDescription() { + return description; + } + + public int getResponseTime() { + return responseTime; + } + + public int getHealthcheckInterval() { + return healthcheckInterval; + } + + public int getHealthcheckThresshold() { + return healthcheckThresshold; + } + + public int getUnhealthThresshold() { + return unhealthThresshold; + } + + public boolean isRevoked() { + return _revoke; + } + + } + public static class LbDestination implements Destination { private int portStart; private int portEnd; @@ -191,10 +258,12 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { public String getIpAddress() { return ip; } + @Override public int getDestinationPortStart() { return portStart; } + @Override public int getDestinationPortEnd() { return portEnd; @@ -230,15 +299,16 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { return null; } - @Override public TrafficType getTrafficType() { return null; } + @Override public FirewallRuleType getType() { return FirewallRuleType.User; } + public LbAutoScaleVmGroup getAutoScaleVmGroup() { return autoScaleVmGroup; } @@ -274,8 +344,7 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { private final AutoScalePolicy policy; private boolean revoked; - public LbAutoScalePolicy(AutoScalePolicy policy, List conditions) - { + public LbAutoScalePolicy(AutoScalePolicy policy, List conditions) { this.policy = policy; this.conditions = conditions; } @@ -309,7 +378,9 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { private final String networkId; private final String vmName; - public LbAutoScaleVmProfile(AutoScaleVmProfile profile, String autoScaleUserApiKey, String autoScaleUserSecretKey, String csUrl, String zoneId, String domainId, String serviceOfferingId, String templateId, String vmName, String networkId) { + public LbAutoScaleVmProfile(AutoScaleVmProfile profile, String autoScaleUserApiKey, + String autoScaleUserSecretKey, String csUrl, String zoneId, String domainId, String serviceOfferingId, + String templateId, String vmName, String networkId) { this.profile = profile; this.autoScaleUserApiKey = autoScaleUserApiKey; this.autoScaleUserSecretKey = autoScaleUserSecretKey; @@ -369,7 +440,8 @@ public class LoadBalancingRule implements FirewallRule, LoadBalancer { private final LbAutoScaleVmProfile profile; private final String currentState; - public LbAutoScaleVmGroup(AutoScaleVmGroup vmGroup, List policies, LbAutoScaleVmProfile profile, String currentState) { + public LbAutoScaleVmGroup(AutoScaleVmGroup vmGroup, List policies, + LbAutoScaleVmProfile profile, String currentState) { this.vmGroup = vmGroup; this.policies = policies; this.profile = profile; diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index 3743aae4bf8..ed39bedaa6f 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -18,8 +18,10 @@ package com.cloud.network.lb; import java.util.List; +import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.ListLBHealthCheckPoliciesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLBStickinessPoliciesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRuleInstancesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRulesCmd; @@ -28,6 +30,8 @@ import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRul import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; +import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.StickinessPolicy; import com.cloud.uservm.UserVm; @@ -66,6 +70,22 @@ public interface LoadBalancingRulesService { public boolean applyLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd) throws ResourceUnavailableException; boolean deleteLBStickinessPolicy(long stickinessPolicyId, boolean apply); + + /** + * Create a healthcheck policy to a load balancer from the given healthcheck + * parameters in (name,value) pairs. + * + * @param cmd + * the command specifying the stickiness method name, params + * (name,value pairs), policy name and description. + * @return the newly created stickiness policy if successfull, null + * otherwise + * @thows NetworkRuleConflictException + */ + public HealthCheckPolicy createLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd cmd); + public boolean applyLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd cmd) throws ResourceUnavailableException; + boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply); + /** * Assign a virtual machine, or list of virtual machines, to a load balancer. */ @@ -104,8 +124,18 @@ public interface LoadBalancingRulesService { */ List searchForLBStickinessPolicies(ListLBStickinessPoliciesCmd cmd); + /** + * List healthcheck policies based on the given criteria + * + * @param cmd + * the command specifies the load balancing rule id. + * @return list of healthcheck policies that match the criteria. + */ + + List searchForLBHealthCheckPolicies(ListLBHealthCheckPoliciesCmd cmd); + List listByNetworkId(long networkId); LoadBalancer findById(long LoadBalancer); - + public void updateLBHealthChecks() throws ResourceUnavailableException; } diff --git a/api/src/com/cloud/network/rules/HealthCheckPolicy.java b/api/src/com/cloud/network/rules/HealthCheckPolicy.java new file mode 100644 index 00000000000..96bb28204a2 --- /dev/null +++ b/api/src/com/cloud/network/rules/HealthCheckPolicy.java @@ -0,0 +1,45 @@ +// 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. +package com.cloud.network.rules; + +import java.util.List; + +import com.cloud.utils.Pair; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +/** + */ +public interface HealthCheckPolicy extends InternalIdentity, Identity { + + public long getLoadBalancerId(); + + public String getpingpath(); + + public String getDescription(); + + public int getResponseTime(); + + public int getHealthcheckInterval(); + + public int getHealthcheckThresshold(); + + public int getUnhealthThresshold(); + + public boolean isRevoke(); + +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index b40b26ce57c..f4c6c527d1a 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -460,6 +460,11 @@ public class ApiConstants { public static final String UCS_BLADE_ID = "bladeid"; public static final String VM_GUEST_IP = "vmguestip"; public static final String OLDER_THAN = "olderthan"; + public static final String HEALTHCHECK_RESPONSE_TIMEOUT = "responsetimeout"; + public static final String HEALTHCHECK_INTERVAL_TIME = "intervaltime"; + public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; + public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; + public static final String HEALTHCHECK_PINGPATH = "pingpath"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index a6025149846..628a185e93d 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -47,6 +47,7 @@ import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.IpForwardingRuleResponse; +import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.LDAPConfigResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; @@ -133,6 +134,7 @@ import com.cloud.network.as.Condition; import com.cloud.network.as.Counter; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.StaticNatRule; @@ -213,6 +215,11 @@ public interface ResponseGenerator { LBStickinessResponse createLBStickinessPolicyResponse(StickinessPolicy stickinessPolicy, LoadBalancer lb); + LBHealthCheckResponse createLBHealthCheckPolicyResponse(List healthcheckPolicies, + LoadBalancer lb); + + LBHealthCheckResponse createLBHealthCheckPolicyResponse(HealthCheckPolicy healthcheckPolicy, LoadBalancer lb); + PodResponse createPodResponse(Pod pod, Boolean showCapacities); ZoneResponse createZoneResponse(DataCenter dataCenter, Boolean showCapacities); diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java new file mode 100644 index 00000000000..ac0ec3a9dab --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/CreateLBHealthCheckPolicyCmd.java @@ -0,0 +1,168 @@ +// 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. +package org.apache.cloudstack.api.command.user.loadbalancer; + + +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.rules.HealthCheckPolicy; +import org.apache.cloudstack.api.response.LBHealthCheckResponse; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + + +@APICommand(name = "createLBHealthCheckPolicy", description = "Creates a Load Balancer healthcheck policy ", responseObject = LBHealthCheckResponse.class, since="4.2.0") +@SuppressWarnings("rawtypes") +public class CreateLBHealthCheckPolicyCmd extends BaseAsyncCreateCmd { + public static final Logger s_logger = Logger + .getLogger(CreateLBHealthCheckPolicyCmd.class.getName()); + + private static final String s_name = "createlbhealthcheckpolicyresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.LBID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the load balancer rule") + private Long lbRuleId; + + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "the description of the load balancer HealthCheck policy") + private String description; + + @Parameter(name = ApiConstants.HEALTHCHECK_PINGPATH, type = CommandType.STRING, required = false, description = "HTTP Ping Path") + private String pingPath; + + @Parameter(name = ApiConstants.HEALTHCHECK_RESPONSE_TIMEOUT, type = CommandType.INTEGER, required = false, description = "Time to wait when receiving a response from the health check (2sec - 60 sec)") + private int responsTimeOut; + + @Parameter(name = ApiConstants.HEALTHCHECK_INTERVAL_TIME, type = CommandType.INTEGER, required = false, description = "Amount of time between health checks (1 sec - 20940 sec)") + private int healthCheckInterval; + + @Parameter(name = ApiConstants.HEALTHCHECK_HEALTHY_THRESHOLD, type = CommandType.INTEGER, required = false, description = "Number of consecutive health check success before declaring an instance healthy") + private int healthyThreshold; + + @Parameter(name = ApiConstants.HEALTHCHECK_UNHEALTHY_THRESHOLD, type = CommandType.INTEGER, required = false, description = "Number of consecutive health check failures before declaring an instance unhealthy") + private int unhealthyThreshold; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getLbRuleId() { + return lbRuleId; + } + + public String getDescription() { + return description; + } + + public String getPingPath() { + return pingPath; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + public int getResponsTimeOut() { + return responsTimeOut; + } + + public int getHealthCheckInterval() { + return healthCheckInterval; + } + + public int getHealthyThreshold() { + return healthyThreshold; + } + + public int getUnhealthyThreshold() { + return unhealthyThreshold; + } + + @Override + public void execute() throws ResourceAllocationException, ResourceUnavailableException { + HealthCheckPolicy policy = null; + boolean success = false; + + try { + UserContext.current().setEventDetails("Load balancer healthcheck policy Id : " + getEntityId()); + success = _lbService.applyLBHealthCheckPolicy(this); + if (success) { + // State might be different after the rule is applied, so get new object here + policy = _entityMgr.findById(HealthCheckPolicy.class, getEntityId()); + LoadBalancer lb = _lbService.findById(policy.getLoadBalancerId()); + LBHealthCheckResponse hcResponse = _responseGenerator.createLBHealthCheckPolicyResponse(policy, lb); + setResponseObject(hcResponse); + hcResponse.setResponseName(getCommandName()); + } + } finally { + if (!success || (policy == null)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create healthcheck policy "); + } + } + } + + @Override + public void create() { + try { + HealthCheckPolicy result = _lbService.createLBHealthCheckPolicy(this); + this.setEntityId(result.getId()); + this.setEntityUuid(result.getUuid()); + } catch (InvalidParameterValueException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.MALFORMED_PARAMETER_ERROR , e.getMessage()); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_HEALTHCHECKPOLICY_CREATE; + } + + @Override + public String getEventDescription() { + return "Create Load Balancer HealthCheck policy"; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java new file mode 100644 index 00000000000..bf91da51d68 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/DeleteLBHealthCheckPolicyCmd.java @@ -0,0 +1,116 @@ +// 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. +package org.apache.cloudstack.api.command.user.loadbalancer; + +import org.apache.cloudstack.api.response.LBHealthCheckResponse; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@APICommand(name = "deleteLBHealthCheckPolicy", description = "Deletes a load balancer HealthCheck policy.", responseObject = SuccessResponse.class, since="4.2.0") +public class DeleteLBHealthCheckPolicyCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeleteLBHealthCheckPolicyCmd.class.getName()); + private static final String s_name = "deletelbhealthcheckpolicyresponse"; + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = LBHealthCheckResponse.class, + required = true, description = "the ID of the load balancer HealthCheck policy") + private Long id; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public String getEventType() { + return EventTypes.EVENT_LB_HEALTHCHECKPOLICY_DELETE; + } + + @Override + public String getEventDescription() { + return "deleting load balancer HealthCheck policy: " + getId(); + } + + @Override + public void execute() { + UserContext.current().setEventDetails("Load balancer healthcheck policy Id: " + getId()); + boolean result = _lbService.deleteLBHealthCheckPolicy(getId() , true); + + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete load balancer healthcheck policy"); + } + } + + @Override + public String getSyncObjType() { + return BaseAsyncCmd.networkSyncObject; + } + + @Override + public Long getSyncObjId() { + HealthCheckPolicy policy = _entityMgr.findById(HealthCheckPolicy.class, + getId()); + if (policy == null) { + throw new InvalidParameterValueException("Unable to find load balancer healthcheck rule: " + id); + } + LoadBalancer lb = _lbService.findById(policy.getLoadBalancerId()); + if (lb == null) { + throw new InvalidParameterValueException("Unable to find load balancer rule for healthcheck rule: " + id); + } + return lb.getNetworkId(); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java new file mode 100644 index 00000000000..cf5ea3238b8 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBHealthCheckPoliciesCmd.java @@ -0,0 +1,85 @@ +// 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. +package org.apache.cloudstack.api.command.user.loadbalancer; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.LBHealthCheckResponse; +import org.apache.cloudstack.api.response.LBStickinessResponse; +import org.apache.cloudstack.api.response.ListResponse; + +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@APICommand(name = "listLBHealthCheckPolicies", description = "Lists load balancer HealthCheck policies.", responseObject = LBHealthCheckResponse.class, since="4.2.0") +public class ListLBHealthCheckPoliciesCmd extends BaseListCmd { + public static final Logger s_logger = Logger + .getLogger(ListLBHealthCheckPoliciesCmd.class.getName()); + + private static final String s_name = "listlbhealthcheckpoliciesresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + @Parameter(name = ApiConstants.LBID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, + required = true, description = "the ID of the load balancer rule") + private Long lbRuleId; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + public Long getLbRuleId() { + return lbRuleId; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() { + List hcpResponses = new ArrayList(); + LoadBalancer lb = _lbService.findById(getLbRuleId()); + ListResponse response = new ListResponse(); + + if (lb != null) { + List healthCheckPolicies = _lbService.searchForLBHealthCheckPolicies(this); + LBHealthCheckResponse spResponse = _responseGenerator.createLBHealthCheckPolicyResponse(healthCheckPolicies, lb); + hcpResponses.add(spResponse); + response.setResponses(hcpResponses); + } + + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } + +} diff --git a/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java b/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java new file mode 100644 index 00000000000..5dd123c03a3 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/LBHealthCheckPolicyResponse.java @@ -0,0 +1,98 @@ +// 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. +package org.apache.cloudstack.api.response; + +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponse; + +public class LBHealthCheckPolicyResponse extends BaseResponse { + @SerializedName("id") + @Param(description = "the LB HealthCheck policy ID") + private String id; + + @SerializedName("pingpath") + @Param(description = "the pingpath of the healthcheck policy") + private String pingpath; + + @SerializedName("description") + @Param(description = "the description of the healthcheck policy") + private String description; + + @SerializedName("state") + @Param(description = "the state of the policy") + private String state; + + @SerializedName("responsetime") + @Param(description = "Time to wait when receiving a response from the health check") + private int responseTime; + + @SerializedName("healthcheckinterval") + @Param(description = "Amount of time between health checks") + private int healthcheckInterval; + + @SerializedName("healthcheckthresshold") + @Param(description = "Number of consecutive health check success before declaring an instance healthy") + private int healthcheckthresshold; + + @SerializedName("unhealthcheckthresshold") + @Param(description = "Number of consecutive health check failures before declaring an instance unhealthy.") + private int unhealthcheckthresshold; + + public void setId(String id) { + this.id = id; + } + + public String getpingpath() { + return pingpath; + } + + public void setpingpath(String pingpath) { + this.pingpath = pingpath; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public LBHealthCheckPolicyResponse(HealthCheckPolicy healthcheckpolicy) { + if (healthcheckpolicy.isRevoke()) { + this.setState("Revoked"); + } + if (healthcheckpolicy.getUuid() != null) + setId(healthcheckpolicy.getUuid()); + this.pingpath = healthcheckpolicy.getpingpath(); + this.healthcheckInterval = healthcheckpolicy.getHealthcheckInterval(); + this.responseTime = healthcheckpolicy.getResponseTime(); + this.healthcheckthresshold = healthcheckpolicy.getHealthcheckThresshold(); + this.unhealthcheckthresshold = healthcheckpolicy.getUnhealthThresshold(); + setObjectName("healthcheckpolicy"); + } +} diff --git a/api/src/org/apache/cloudstack/api/response/LBHealthCheckResponse.java b/api/src/org/apache/cloudstack/api/response/LBHealthCheckResponse.java new file mode 100644 index 00000000000..182013ffef0 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/LBHealthCheckResponse.java @@ -0,0 +1,102 @@ +// 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. +package org.apache.cloudstack.api.response; + +import com.cloud.network.rules.HealthCheckPolicy; +import org.apache.cloudstack.api.ApiConstants; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import java.util.List; +import java.util.UUID; + +@EntityReference(value=HealthCheckPolicy.class) +public class LBHealthCheckResponse extends BaseResponse { +@SerializedName("lbruleid") + @Param(description = "the LB rule ID") + private String lbRuleId; + + + @SerializedName("account") + @Param(description = "the account of the HealthCheck policy") + private String accountName; + + @SerializedName(ApiConstants.DOMAIN_ID) + @Param(description = "the domain ID of the HealthCheck policy") + private String domainId; + + @SerializedName("domain") + @Param(description = "the domain of the HealthCheck policy") + private String domainName; + + @SerializedName(ApiConstants.ZONE_ID) + @Param(description = "the id of the zone the HealthCheck policy belongs to") + private String zoneId; + + @SerializedName("healthcheckpolicy") + @Param(description = "the list of healthcheckpolicies", responseObject = LBHealthCheckPolicyResponse.class) + private List healthCheckPolicies; + + public void setlbRuleId(String lbRuleId) { + this.lbRuleId = lbRuleId; + } + + public void setRules(List policies) { + this.healthCheckPolicies = policies; + } + + public List getHealthCheckPolicies() { + return healthCheckPolicies; + } + + public void setHealthCheckPolicies(List healthCheckPolicies) { + this.healthCheckPolicies = healthCheckPolicies; + } + + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + public LBHealthCheckResponse() { + } + + public LBHealthCheckResponse(HealthCheckPolicy healthcheckpolicy) { + setObjectName("healthcheckpolicy"); + } +} diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 5018236e5e2..382573b864c 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -151,6 +151,9 @@ createLBStickinessPolicy=15 deleteLBStickinessPolicy=15 listLoadBalancerRules=15 listLBStickinessPolicies=15 +listLBHealthCheckPolicies=15 +createLBHealthCheckPolicy=15 +deleteLBHealthCheckPolicy=15 listLoadBalancerRuleInstances=15 updateLoadBalancerRule=15 diff --git a/plugins/network-elements/dns-notifier/resources/components-example.xml b/plugins/network-elements/dns-notifier/resources/components-example.xml index 36441bd667b..3a92a258e9f 100755 --- a/plugins/network-elements/dns-notifier/resources/components-example.xml +++ b/plugins/network-elements/dns-notifier/resources/components-example.xml @@ -155,6 +155,8 @@ under the License. + + diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java index abb36c36963..bebba3cb09d 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/element/ElasticLoadBalancerElement.java @@ -28,6 +28,7 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.deploy.DeployDestination; @@ -197,4 +198,10 @@ public class ElasticLoadBalancerElement extends AdapterBase implements LoadBalan public IpDeployer getIpDeployer(Network network) { return this; } + + @Override + public List updateHealthChecks(Network network, List lbrules) { + return null; + } + } diff --git a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java index 81039d1f3c7..283b517dce9 100644 --- a/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java +++ b/plugins/network-elements/elastic-loadbalancer/src/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java @@ -94,6 +94,7 @@ import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.lb.dao.ElasticLbVmMapDao; import com.cloud.network.router.VirtualRouter; @@ -367,9 +368,10 @@ ElasticLoadBalancerManager, VirtualMachineGuru { for (LoadBalancerVO lb : lbs) { List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); + List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); LoadBalancingRule loadBalancing = new LoadBalancingRule( - lb, dstList, policyList); - lbRules.add(loadBalancing); + lb, dstList, policyList, hcPolicyList); + lbRules.add(loadBalancing); } return applyLBRules(elbVm, lbRules, network.getId()); } else if (elbVm.getState() == State.Stopped @@ -940,7 +942,8 @@ ElasticLoadBalancerManager, VirtualMachineGuru { for (LoadBalancerVO lb : lbs) { List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList); + List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); lbRules.add(loadBalancing); } diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 94c098ed4bb..3e75c3f1afe 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.response.ExternalLoadBalancerResponse; import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; import org.apache.log4j.Logger; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.api.ApiDBUtils; import com.cloud.api.commands.AddExternalLoadBalancerCmd; import com.cloud.api.commands.AddF5LoadBalancerCmd; @@ -496,4 +497,11 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan } return this; } + + @Override + public List updateHealthChecks(Network network, + List lbrules) { + // TODO Auto-generated method stub + return null; + } } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index c1c735aa270..a90440cc2f3 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -292,7 +292,8 @@ StaticNatServiceProvider { lbCapabilities.put(Capability.SupportedStickinessMethods, stickyMethodList); lbCapabilities.put(Capability.ElasticLb, "true"); - + //Setting HealthCheck Capability to True for Netscaler element + lbCapabilities.put(Capability.HealthCheckPolicy, "true"); capabilities.put(Service.Lb, lbCapabilities); Map staticNatCapabilities = new HashMap(); @@ -814,4 +815,26 @@ StaticNatServiceProvider { } return null; } + + @Override + public List updateHealthChecks(Network network, List lbrules) { + + if (canHandle(network, Service.Lb)) { + try { + return getLBHealthChecks(network, lbrules); + } catch (ResourceUnavailableException e) { + s_logger.error("Error in getting the LB Rules from NetScaler " + e); + } + } else { + s_logger.error("Network cannot handle to LB service "); + } + return null; + } + + @Override + public List getLBHealthChecks(Network network, List rules) + throws ResourceUnavailableException { + return super.getLBHealthChecks(network, rules); + + } } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index abea4649dbe..4eb0ce2065d 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -11,11 +11,12 @@ // 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 +// KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.network.resource; +import java.util.ArrayList; import java.util.Formatter; import java.util.HashMap; import java.util.List; @@ -31,6 +32,7 @@ import com.citrix.netscaler.nitro.resource.base.base_response; import com.citrix.netscaler.nitro.resource.config.autoscale.autoscalepolicy; import com.citrix.netscaler.nitro.resource.config.autoscale.autoscaleprofile; import com.citrix.netscaler.nitro.resource.config.basic.server_service_binding; +import com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding; import com.citrix.netscaler.nitro.resource.config.basic.servicegroup; import com.citrix.netscaler.nitro.resource.config.basic.servicegroup_lbmonitor_binding; import com.citrix.netscaler.nitro.resource.config.lb.lbmetrictable; @@ -71,6 +73,8 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupExternalLoadBalancerCommand; import com.cloud.agent.api.routing.CreateLoadBalancerApplianceCommand; import com.cloud.agent.api.routing.DestroyLoadBalancerApplianceCommand; +import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer; +import com.cloud.agent.api.routing.HealthCheckLBConfigCommand; import com.cloud.agent.api.routing.IpAssocAnswer; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; @@ -84,6 +88,7 @@ import com.cloud.agent.api.to.LoadBalancerTO.AutoScaleVmProfileTO; import com.cloud.agent.api.to.LoadBalancerTO.ConditionTO; import com.cloud.agent.api.to.LoadBalancerTO.CounterTO; import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO; +import com.cloud.agent.api.to.LoadBalancerTO.HealthCheckPolicyTO; import com.cloud.agent.api.to.LoadBalancerTO.StickinessPolicyTO; import com.cloud.agent.api.to.StaticNatRuleTO; import org.apache.cloudstack.api.ApiConstants; @@ -396,12 +401,14 @@ public class NetscalerResource implements ServerResource { return execute((DestroyLoadBalancerApplianceCommand) cmd, numRetries); } else if (cmd instanceof SetStaticNatRulesCommand) { return execute((SetStaticNatRulesCommand) cmd, numRetries); - } else { + } else if (cmd instanceof HealthCheckLBConfigCommand) { + return execute((HealthCheckLBConfigCommand) cmd, numRetries); + }else { return Answer.createUnsupportedCommandAnswer(cmd); } } - private Answer execute(ReadyCommand cmd) { + private Answer execute(ReadyCommand cmd) { return new ReadyAnswer(cmd); } @@ -450,6 +457,65 @@ public class NetscalerResource implements ServerResource { return new IpAssocAnswer(cmd, results); } + private Answer execute(HealthCheckLBConfigCommand cmd, int numRetries) { + + List hcLB = new ArrayList(); + try { + + if (_isSdx) { + return Answer.createUnsupportedCommandAnswer(cmd); + } + + LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers(); + + if (loadBalancers == null) { + return new HealthCheckLBConfigAnswer(hcLB); + } + + for (LoadBalancerTO loadBalancer : loadBalancers) { + HealthCheckPolicyTO[] healthCheckPolicies = loadBalancer.getHealthCheckPolicies(); + if ((healthCheckPolicies != null) && (healthCheckPolicies.length > 0) + && (healthCheckPolicies[0] != null)) { + String nsVirtualServerName = generateNSVirtualServerName(loadBalancer.getSrcIp(), + loadBalancer.getSrcPort()); + + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding + .get(_netscalerService, nsVirtualServerName); + + if (serviceBindings != null) { + for (DestinationTO destination : loadBalancer.getDestinations()) { + String nsServiceName = generateNSServiceName(destination.getDestIp(), + destination.getDestPort()); + for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { + if (nsServiceName.equalsIgnoreCase(binding.get_servicename())) { + destination.setMonitorState(binding.get_curstate()); + break; + } + } + } + hcLB.add(loadBalancer); + } + } + } + + } catch (ExecutionException e) { + s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e); + if (shouldRetry(numRetries)) { + return retry(cmd, numRetries); + } else { + return new HealthCheckLBConfigAnswer(hcLB); + } + } catch (Exception e) { + s_logger.error("Failed to execute HealthCheckLBConfigCommand due to ", e); + if (shouldRetry(numRetries)) { + return retry(cmd, numRetries); + } else { + return new HealthCheckLBConfigAnswer(hcLB); + } + } + return new HealthCheckLBConfigAnswer(hcLB); + } + private synchronized Answer execute(LoadBalancerConfigCommand cmd, int numRetries) { try { if (_isSdx) { @@ -467,12 +533,13 @@ public class NetscalerResource implements ServerResource { String lbProtocol = getNetScalerProtocol(loadBalancer); String lbAlgorithm = loadBalancer.getAlgorithm(); String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort); - + String nsMonitorName = generateNSMonitorName(srcIp, srcPort); if(loadBalancer.isAutoScaleVmGroupTO()) { applyAutoScaleConfig(loadBalancer); return new Answer(cmd); } - + boolean hasMonitor = false; + boolean deleteMonitor = false; boolean destinationsToAdd = false; for (DestinationTO destination : loadBalancer.getDestinations()) { if (!destination.isRevoked()) { @@ -489,11 +556,28 @@ public class NetscalerResource implements ServerResource { s_logger.debug("Created load balancing virtual server " + nsVirtualServerName + " on the Netscaler device"); } + // create a new monitor + HealthCheckPolicyTO[] healthCheckPolicies = loadBalancer.getHealthCheckPolicies(); + if ((healthCheckPolicies != null) && (healthCheckPolicies.length > 0) + && (healthCheckPolicies[0] != null)) { + + for (HealthCheckPolicyTO healthCheckPolicyTO : healthCheckPolicies) { + if ( !healthCheckPolicyTO.isRevoked() ) { + addLBMonitor(nsMonitorName, lbProtocol, healthCheckPolicyTO); + hasMonitor = true; + } + else { + deleteMonitor = true; + hasMonitor = false; + } + } + + } + for (DestinationTO destination : loadBalancer.getDestinations()) { String nsServerName = generateNSServerName(destination.getDestIp()); String nsServiceName = generateNSServiceName(destination.getDestIp(), destination.getDestPort()); - if (!destination.isRevoked()) { // add a new destination to deployed load balancing rule @@ -534,6 +618,26 @@ public class NetscalerResource implements ServerResource { throw new ExecutionException("Failed to bind service: " + nsServiceName + " to the lb virtual server: " + nsVirtualServerName + " on Netscaler device"); } } + + // After binding the service to the LB Vserver + // successfully, bind the created monitor to the + // service. + if (hasMonitor) { + if (!isServiceBoundToMonitor(nsServiceName, nsMonitorName)) { + bindServiceToMonitor(nsServiceName, nsMonitorName); + } + } else { + // check if any monitor created by CS is already + // existing, if yes, unbind it from services and + // delete it. + if (nsMonitorExist(nsMonitorName)) { + // unbind the service from the monitor and + // delete the monitor + unBindServiceToMonitor(nsServiceName, nsMonitorName); + deleteMonitor = true; + } + + } if (s_logger.isDebugEnabled()) { s_logger.debug("Successfully added LB destination: " + destination.getDestIp() + ":" + destination.getDestPort() + " to load balancer " + srcIp + ":" + srcPort); } @@ -609,8 +713,13 @@ public class NetscalerResource implements ServerResource { } } removeLBVirtualServer(nsVirtualServerName); + deleteMonitor = true; } } + if(deleteMonitor) { + removeLBMonitor(nsMonitorName); + } + } if (s_logger.isInfoEnabled()) { @@ -1223,23 +1332,64 @@ public class NetscalerResource implements ServerResource { } } + private lbmonitor getMonitorIfExisits(String lbMonitorName) throws ExecutionException { + try { + return lbmonitor.get(_netscalerService, lbMonitorName); + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return null; + } else { + throw new ExecutionException(e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException(e.getMessage()); + } + } + private boolean isServiceBoundToVirtualServer(String serviceName) throws ExecutionException { try { lbvserver[] lbservers = lbvserver.get(_netscalerService); for (lbvserver vserver : lbservers) { filtervalue[] filter = new filtervalue[1]; filter[0] = new filtervalue("servicename", serviceName); - lbvserver_service_binding[] result = lbvserver_service_binding.get_filtered(_netscalerService, vserver.get_name(), filter); + lbvserver_service_binding[] result = lbvserver_service_binding.get_filtered(_netscalerService, + vserver.get_name(), filter); if (result != null && result.length > 0) { return true; } } return false; } catch (Exception e) { - throw new ExecutionException("Failed to verify service " + serviceName + " is bound to any virtual server due to " + e.getMessage()); + throw new ExecutionException("Failed to verify service " + serviceName + + " is bound to any virtual server due to " + e.getMessage()); } } + private boolean isServiceBoundToMonitor(String nsServiceName, String nsMonitorName) throws ExecutionException { + + filtervalue[] filter = new filtervalue[1]; + filter[0] = new filtervalue("monitor_name", nsMonitorName); + service_lbmonitor_binding[] result; + try { + result = service_lbmonitor_binding.get_filtered(_netscalerService, nsServiceName, filter); + if (result != null && result.length > 0) { + return true; + } + + } catch (Exception e) { + throw new ExecutionException("Failed to verify service " + nsServiceName + + " is bound to any monitor due to " + e.getMessage()); + } + return false; + } + + private boolean nsMonitorExist(String nsMonitorname) throws ExecutionException { + if (getMonitorIfExisits(nsMonitorname) != null) + return true; + else + return false; + } + private boolean nsServiceExists(String serviceName) throws ExecutionException { try { if (com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName) != null) { @@ -1480,6 +1630,126 @@ public class NetscalerResource implements ServerResource { } } + // Monitor related methods + private void addLBMonitor(String nsMonitorName, String lbProtocol, HealthCheckPolicyTO hcp) + throws ExecutionException { + try { + // check if the monitor exists + boolean csMonitorExisis = false; + lbmonitor csMonitor = getMonitorIfExisits(nsMonitorName); + if (csMonitor != null) { + if (!csMonitor.get_type().equalsIgnoreCase(lbProtocol)) { + throw new ExecutionException("Can not update monitor :" + nsMonitorName + " as current protocol:" + + csMonitor.get_type() + " of monitor is different from the " + " intended protocol:" + + lbProtocol); + } + csMonitorExisis = true; + } + if (!csMonitorExisis) { + lbmonitor csMon = new lbmonitor(); + csMon.set_monitorname(nsMonitorName); + csMon.set_type(lbProtocol); + if (lbProtocol.equalsIgnoreCase("HTTP")) { + csMon.set_httprequest(hcp.getpingPath()); + s_logger.trace("LB Protocol is HTTP, Applying ping path on HealthCheck Policy"); + } else { + s_logger.debug("LB Protocol is not HTTP, Skipping to apply ping path on HealthCheck Policy"); + } + + csMon.set_interval(hcp.getHealthcheckInterval()); + csMon.set_resptimeout(hcp.getResponseTime()); + csMon.set_failureretries(hcp.getUnhealthThresshold()); + csMon.set_successretries(hcp.getHealthcheckThresshold()); + s_logger.debug("Monitor properites going to get created :interval :: " + csMon.get_interval() + "respTimeOUt:: " + csMon.get_resptimeout() + +"failure retires(unhealththresshold) :: " + csMon.get_failureretries() + "successtries(healththresshold) ::" + csMon.get_successretries()); + lbmonitor.add(_netscalerService, csMon); + } else { + s_logger.debug("Monitor :" + nsMonitorName + " is already existing. Skipping to delete and create it"); + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed to create new monitor :" + nsMonitorName + " due to " + e.getMessage()); + } catch (Exception e) { + throw new ExecutionException("Failed to create new monitor :" + nsMonitorName + " due to " + e.getMessage()); + } + } + + private void bindServiceToMonitor(String nsServiceName, String nsMonitorName) throws ExecutionException { + + try { + com.citrix.netscaler.nitro.resource.config.basic.service serviceObject = new com.citrix.netscaler.nitro.resource.config.basic.service(); + serviceObject = com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, + nsServiceName); + if (serviceObject != null) { + com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding serviceMonitor = new com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding(); + serviceMonitor.set_monitor_name(nsMonitorName); + serviceMonitor.set_name(nsServiceName); + serviceMonitor.set_monstate("ENABLED"); + s_logger.debug("Trying to bind the monitor :" + nsMonitorName + " to the service :" + nsServiceName); + com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding.add(_netscalerService, + serviceMonitor); + s_logger.debug("Successfully binded the monitor :" + nsMonitorName + " to the service :" + + nsServiceName); + } + } catch (nitro_exception e) { + throw new ExecutionException("Failed to create new monitor :" + nsMonitorName + " due to " + e.getMessage()); + } catch (Exception e) { + throw new ExecutionException("Failed to create new monitor :" + nsMonitorName + " due to " + e.getMessage()); + } + } + + private void unBindServiceToMonitor(String nsServiceName, String nsMonitorName) throws ExecutionException { + + try { + com.citrix.netscaler.nitro.resource.config.basic.service serviceObject = new com.citrix.netscaler.nitro.resource.config.basic.service(); + serviceObject = com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, + nsServiceName); + + if (serviceObject != null) { + com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding serviceMonitor = new com.citrix.netscaler.nitro.resource.config.basic.service_lbmonitor_binding(); + serviceMonitor.set_monitor_name(nsMonitorName); + serviceMonitor.set_name(nsServiceName); + s_logger.debug("Trying to unbind the monitor :" + nsMonitorName + " from the service :" + + nsServiceName); + service_lbmonitor_binding.delete(_netscalerService, serviceMonitor); + s_logger.debug("Successfully unbinded the monitor :" + nsMonitorName + " from the service :" + + nsServiceName); + } + + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return; + } else { + throw new ExecutionException("Failed to unbind monitor :" + nsMonitorName + "from the service :" + + nsServiceName + "due to " + e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException("Failed to unbind monitor :" + nsMonitorName + "from the service :" + + nsServiceName + "due to " + e.getMessage()); + } + + } + + private void removeLBMonitor(String nsMonitorName) throws ExecutionException { + + try { + if (nsMonitorExist(nsMonitorName)) { + lbmonitor monitorObj = lbmonitor.get(_netscalerService, nsMonitorName); + monitorObj.set_respcode(null); + lbmonitor.delete(_netscalerService, monitorObj); + s_logger.info("Successfully deleted monitor : " + nsMonitorName); + } + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return; + } else { + throw new ExecutionException("Failed to delete monitor :" + nsMonitorName + " due to " + e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException("Failed to delete monitor :" + nsMonitorName + " due to " + e.getMessage()); + } + + } + public synchronized void applyAutoScaleConfig(LoadBalancerTO loadBalancer) throws Exception, ExecutionException { AutoScaleVmGroupTO vmGroupTO = loadBalancer.getAutoScaleVmGroupTO(); @@ -2229,6 +2499,11 @@ public class NetscalerResource implements ServerResource { return genObjectName("Cloud-VirtualServer", srcIp, srcPort); } + private String generateNSMonitorName(String srcIp, long srcPort) { + // maximum length supported by NS is 31 + return genObjectName("Cloud-Hc", srcIp, srcPort); + } + private String generateNSServerName(String serverIP) { return genObjectName("Cloud-Server-", serverIP); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 2546f292883..ebf0fcf73d3 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -46,6 +46,8 @@ import org.apache.cloudstack.api.response.ControlledViewEntityResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.IpForwardingRuleResponse; +import org.apache.cloudstack.api.response.LBHealthCheckPolicyResponse; +import org.apache.cloudstack.api.response.LBHealthCheckResponse; import org.apache.cloudstack.api.response.LBStickinessPolicyResponse; import org.apache.cloudstack.api.response.LBStickinessResponse; import org.apache.cloudstack.api.response.LDAPConfigResponse; @@ -143,6 +145,13 @@ import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.*; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; @@ -2750,6 +2759,58 @@ public class ApiResponseHelper implements ResponseGenerator { return spResponse; } + @Override + public LBHealthCheckResponse createLBHealthCheckPolicyResponse( + List healthcheckPolicies, LoadBalancer lb) { + LBHealthCheckResponse hcResponse = new LBHealthCheckResponse(); + + if (lb == null) + return hcResponse; + hcResponse.setlbRuleId(lb.getUuid()); + Account account = ApiDBUtils.findAccountById(lb.getAccountId()); + if (account != null) { + hcResponse.setAccountName(account.getAccountName()); + Domain domain = ApiDBUtils.findDomainById(account.getDomainId()); + if (domain != null) { + hcResponse.setDomainId(domain.getUuid()); + hcResponse.setDomainName(domain.getName()); + } + } + + List responses = new ArrayList(); + for (HealthCheckPolicy healthcheckPolicy : healthcheckPolicies) { + LBHealthCheckPolicyResponse ruleResponse = new LBHealthCheckPolicyResponse(healthcheckPolicy); + responses.add(ruleResponse); + } + hcResponse.setRules(responses); + + hcResponse.setObjectName("healthcheckpolicies"); + return hcResponse; + } + + @Override + public LBHealthCheckResponse createLBHealthCheckPolicyResponse(HealthCheckPolicy healthcheckPolicy, LoadBalancer lb) { + LBHealthCheckResponse hcResponse = new LBHealthCheckResponse(); + + hcResponse.setlbRuleId(lb.getUuid()); + Account accountTemp = ApiDBUtils.findAccountById(lb.getAccountId()); + if (accountTemp != null) { + hcResponse.setAccountName(accountTemp.getAccountName()); + Domain domain = ApiDBUtils.findDomainById(accountTemp.getDomainId()); + if (domain != null) { + hcResponse.setDomainId(domain.getUuid()); + hcResponse.setDomainName(domain.getName()); + } + } + + List responses = new ArrayList(); + LBHealthCheckPolicyResponse ruleResponse = new LBHealthCheckPolicyResponse(healthcheckPolicy); + responses.add(ruleResponse); + hcResponse.setRules(responses); + hcResponse.setObjectName("healthcheckpolicies"); + return hcResponse; + } + @Override public LDAPConfigResponse createLDAPConfigResponse(String hostname, Integer port, Boolean useSSL, String queryFilter, diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index d01ea5bbaf1..9db7dbdd89b 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -207,7 +207,11 @@ public enum Config { AlertPurgeInterval("Advanced", ManagementServer.class, Integer.class, "alert.purge.interval", "86400", "The interval (in seconds) to wait before running the alert purge thread", null), AlertPurgeDelay("Advanced", ManagementServer.class, Integer.class, "alert.purge.delay", "0", "Alerts older than specified number days will be purged. Set this value to 0 to never delete alerts", null), - DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled", "false", "Direct-attach VMs using external DHCP server", "true,false"), + // LB HealthCheck Interval. + LBHealthCheck("Advanced", ManagementServer.class, String.class, "healthcheck.update.interval", "600", + "Time Interval to fetch the LB health check states (in sec)", null), + + DirectAttachNetworkEnabled("Advanced", ManagementServer.class, Boolean.class, "direct.attach.network.externalIpAllocator.enabled", "false", "Direct-attach VMs using external DHCP server", "true,false"), DirectAttachNetworkExternalAPIURL("Advanced", ManagementServer.class, String.class, "direct.attach.network.externalIpAllocator.url", null, "Direct-attach VMs using external DHCP server (API url)", null), CheckPodCIDRs("Advanced", ManagementServer.class, String.class, "check.pod.cidrs", "true", "If true, different pods must belong to different CIDR subnets.", "true,false"), NetworkGcWait("Advanced", ManagementServer.class, Integer.class, "network.gc.wait", "600", "Time (in seconds) to wait before shutting down a network that's not in used", null), diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java index d979f079691..dee3ca966e9 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.util.List; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.Host; @@ -96,7 +97,9 @@ public interface ExternalLoadBalancerDeviceManager extends Manager{ * @throws ResourceUnavailableException * @throws InsufficientCapacityException */ - public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, + public boolean manageGuestNetworkWithExternalLoadBalancer(boolean add, Network guestConfig) throws ResourceUnavailableException, InsufficientCapacityException; - + + public List getLBHealthChecks(Network network, List rules) + throws ResourceUnavailableException; } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index d7b6d78c9bb..049099d6b1f 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -34,6 +34,8 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupExternalLoadBalancerCommand; import com.cloud.agent.api.routing.CreateLoadBalancerApplianceCommand; import com.cloud.agent.api.routing.DestroyLoadBalancerApplianceCommand; +import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer; +import com.cloud.agent.api.routing.HealthCheckLBConfigCommand; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.NetworkElementCommand; @@ -888,7 +890,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) { boolean inline = _networkMgr.isNetworkInlineMode(network); - LoadBalancerTO loadBalancer = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, inline, destinations, rule.getStickinessPolicies()); + LoadBalancerTO loadBalancer = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, false, inline, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies()); if (rule.isAutoScaleConfig()) { loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup()); } @@ -1111,4 +1113,95 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase s_logger.info("Let " + element.getName() + " handle ip association for " + getName() + " in network " + network.getId()); return (IpDeployer)element; } + + @Override + public List getLBHealthChecks(Network network, List rules) + throws ResourceUnavailableException { + + // Find the external load balancer in this zone + long zoneId = network.getDataCenterId(); + DataCenterVO zone = _dcDao.findById(zoneId); + HealthCheckLBConfigAnswer answer = null; + + List loadBalancingRules = new ArrayList(); + + for (FirewallRule rule : rules) { + if (rule.getPurpose().equals(Purpose.LoadBalancing)) { + loadBalancingRules.add((LoadBalancingRule) rule); + } + } + + if (loadBalancingRules == null || loadBalancingRules.isEmpty()) { + return null; + } + + ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network); + if (lbDeviceVO == null) { + s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning"); + return null; + } + + HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId()); + + boolean externalLoadBalancerIsInline = _networkMgr.isNetworkInlineMode(network); + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External load balancer was asked to apply LB rules for network with ID " + network.getId() + + "; this network is not implemented. Skipping backend commands."); + return null; + } + + List loadBalancersToApply = new ArrayList(); + List mappingStates = new ArrayList(); + for (int i = 0; i < loadBalancingRules.size(); i++) { + LoadBalancingRule rule = loadBalancingRules.get(i); + + boolean revoked = (rule.getState().equals(FirewallRule.State.Revoke)); + String protocol = rule.getProtocol(); + String algorithm = rule.getAlgorithm(); + String uuid = rule.getUuid(); + String srcIp = _networkModel.getIp(rule.getSourceIpAddressId()).getAddress().addr(); + int srcPort = rule.getSourcePortStart(); + List destinations = rule.getDestinations(); + + if (externalLoadBalancerIsInline) { + MappingNic nic = getLoadBalancingIpNic(zone, network, rule.getSourceIpAddressId(), revoked, null); + mappingStates.add(nic.getState()); + NicVO loadBalancingIpNic = nic.getNic(); + if (loadBalancingIpNic == null) { + continue; + } + + // Change the source IP address for the load balancing rule to + // be the load balancing IP address + srcIp = loadBalancingIpNic.getIp4Address(); + } + + if ((destinations != null && !destinations.isEmpty()) || !rule.isAutoScaleConfig()) { + boolean inline = _networkMgr.isNetworkInlineMode(network); + LoadBalancerTO loadBalancer = new LoadBalancerTO(uuid, srcIp, srcPort, protocol, algorithm, revoked, + false, inline, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies()); + loadBalancersToApply.add(loadBalancer); + } + } + + try { + if (loadBalancersToApply.size() > 0) { + int numLoadBalancersForCommand = loadBalancersToApply.size(); + LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply + .toArray(new LoadBalancerTO[numLoadBalancersForCommand]); + // LoadBalancerConfigCommand cmd = new + // LoadBalancerConfigCommand(loadBalancersForCommand, null); + HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand); + long guestVlanTag = Integer.parseInt(network.getBroadcastUri().getHost()); + cmd.setAccessDetail(NetworkElementCommand.GUEST_VLAN_TAG, String.valueOf(guestVlanTag)); + + answer = (HealthCheckLBConfigAnswer) _agentMgr.easySend(externalLoadBalancer.getId(), cmd); + } + } catch (Exception ex) { + s_logger.error("Exception Occured ", ex); + } + return answer.getLoadBalancers(); + } + } diff --git a/server/src/com/cloud/network/LBHealthCheckPolicyVO.java b/server/src/com/cloud/network/LBHealthCheckPolicyVO.java new file mode 100644 index 00000000000..ed03a2bbc89 --- /dev/null +++ b/server/src/com/cloud/network/LBHealthCheckPolicyVO.java @@ -0,0 +1,157 @@ +// 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. +package com.cloud.network; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.PrimaryKeyJoinColumn; +import javax.persistence.Table; + +import com.cloud.network.rules.HealthCheckPolicy; +import org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name = ("load_balancer_healthcheck_policies")) +@PrimaryKeyJoinColumn(name = "load_balancer_id", referencedColumnName = "id") +public class LBHealthCheckPolicyVO implements HealthCheckPolicy { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "load_balancer_id") + private long loadBalancerId; + + @Column(name = "pingpath") + private String pingPath; + + @Column(name = "description") + private String description; + + @Column(name = "uuid") + private String uuid; + + @Column(name = "response_time") + private int responseTime; + + @Column(name = "healthcheck_interval") + private int healthcheckInterval; + + @Column(name = "healthcheck_thresshold") + private int healthcheckThresshold; + + @Column(name = "unhealth_thresshold") + private int unhealthThresshold; + + @Column(name = "revoke") + private boolean revoke = false; + + protected LBHealthCheckPolicyVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public LBHealthCheckPolicyVO(long loadBalancerId, String pingPath, String description, int responseTime, + int healthcheckInterval, int healthcheckThresshold, int unhealthThresshold) { + this.loadBalancerId = loadBalancerId; + + if (pingPath == null || pingPath.isEmpty()) + this.pingPath = "/"; + else + this.pingPath = pingPath; + + if (responseTime == 0) + this.responseTime = 2; + else + this.responseTime = responseTime; + + if (healthcheckInterval == 0) + this.healthcheckInterval = 5; + else + this.healthcheckInterval = healthcheckInterval; + + if (healthcheckThresshold == 0) + this.healthcheckThresshold = 2; + else + this.healthcheckThresshold = healthcheckThresshold; + + if (unhealthThresshold == 0) + this.unhealthThresshold = 1; + else + this.unhealthThresshold = unhealthThresshold; + this.uuid = UUID.randomUUID().toString(); + + } + + public int getResponseTime() { + return responseTime; + } + + public int getHealthcheckInterval() { + return healthcheckInterval; + } + + public int getHealthcheckThresshold() { + return healthcheckThresshold; + } + + public int getUnhealthThresshold() { + return unhealthThresshold; + } + + public long getId() { + return id; + } + + public long getLoadBalancerId() { + return loadBalancerId; + } + + public String getpingpath() { + return pingPath; + } + + public String getDescription() { + return description; + } + + public boolean isRevoke() { + return revoke; + } + + public void setRevoke(boolean revoke) { + this.revoke = revoke; + } + + @Override + public String getUuid() { + return this.uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 3220c9174eb..591910b13c6 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -106,6 +106,7 @@ import com.cloud.network.element.UserDataServiceProvider; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.rules.*; @@ -2310,52 +2311,51 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @Override public boolean applyRules(List rules, FirewallRule.Purpose purpose, NetworkRuleApplier applier, boolean continueOnError) throws ResourceUnavailableException { - if (rules == null || rules.size() == 0) { - s_logger.debug("There are no rules to forward to the network elements"); - return true; - } + if (rules == null || rules.size() == 0) { + s_logger.debug("There are no rules to forward to the network elements"); + return true; + } - boolean success = true; - Network network = _networksDao.findById(rules.get(0).getNetworkId()); + boolean success = true; + Network network = _networksDao.findById(rules.get(0).getNetworkId()); FirewallRuleVO.TrafficType trafficType = rules.get(0).getTrafficType(); - List publicIps = new ArrayList(); + List publicIps = new ArrayList(); - if (! (rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress)) { + if (!(rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress)) { // get the list of public ip's owned by the network List userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); if (userIps != null && !userIps.isEmpty()) { for (IPAddressVO userIp : userIps) { - PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId())); - publicIps.add(publicIp); - } - } + PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId())); + publicIps.add(publicIp); + } + } - // rules can not programmed unless IP is associated with network service provider, so run IP assoication for - // the network so as to ensure IP is associated before applying rules (in add state) - applyIpAssociations(network, false, continueOnError, publicIps); - } - - try { - applier.applyRules(network, purpose, rules); - } catch (ResourceUnavailableException e) { - if (!continueOnError) { - throw e; - } - s_logger.warn("Problems with applying " + purpose + " rules but pushing on", e); - success = false; - } - - if (! (rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress) ) { - // if all the rules configured on public IP are revoked then dis-associate IP with network service provider + // rules can not programmed unless IP is associated with network + // service provider, so run IP assoication for + // the network so as to ensure IP is associated before applying + // rules (in add state) + applyIpAssociations(network, false, continueOnError, publicIps); + } + + try { + applier.applyRules(network, purpose, rules); + } catch (ResourceUnavailableException e) { + if (!continueOnError) { + throw e; + } + s_logger.warn("Problems with applying " + purpose + " rules but pushing on", e); + success = false; + } + + if (!(rules.get(0).getPurpose() == FirewallRule.Purpose.Firewall && trafficType == FirewallRule.TrafficType.Egress)) { + // if all the rules configured on public IP are revoked then + // dis-associate IP with network service provider applyIpAssociations(network, true, continueOnError, publicIps); } - return success; + return success; } - - - - public class NetworkGarbageCollector implements Runnable { @@ -3099,13 +3099,14 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L lb.setState(FirewallRule.State.Revoke); List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); + List hcPolicyList = _lbMgr.getHealthCheckPolicies (lb.getId()); // mark all destination with revoke state for (LbDestination dst : dstList) { s_logger.trace("Marking lb destination " + dst + " with Revoke state"); dst.setRevoked(true); } - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); lbRules.add(loadBalancing); } diff --git a/server/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java b/server/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java new file mode 100644 index 00000000000..42a9e421485 --- /dev/null +++ b/server/src/com/cloud/network/dao/LBHealthCheckPolicyDao.java @@ -0,0 +1,35 @@ +// 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. +package com.cloud.network.dao; + +import java.util.List; + +import com.cloud.network.LBHealthCheckPolicyVO; +import com.cloud.utils.db.GenericDao; + + +public interface LBHealthCheckPolicyDao extends + GenericDao { + void remove(long loadBalancerId); + + void remove(long loadBalancerId, Boolean pending); + + List listByLoadBalancerId(long loadBalancerId); + + List listByLoadBalancerId(long loadBalancerId, + boolean revoke); +} diff --git a/server/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java b/server/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java new file mode 100644 index 00000000000..65e0689e79a --- /dev/null +++ b/server/src/com/cloud/network/dao/LBHealthCheckPolicyDaoImpl.java @@ -0,0 +1,71 @@ +// 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. +package com.cloud.network.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.network.LBHealthCheckPolicyVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchCriteria; + + +@Component +@Local(value = { LBHealthCheckPolicyDao.class }) +public class LBHealthCheckPolicyDaoImpl extends + GenericDaoBase implements + LBHealthCheckPolicyDao { + + @Override + public void remove(long loadBalancerId) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + + expunge(sc); + } + + @Override + public void remove(long loadBalancerId, Boolean revoke) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("revoke", SearchCriteria.Op.EQ, revoke); + + expunge(sc); + } + + @Override + public List listByLoadBalancerId(long loadBalancerId) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + + return listBy(sc); + } + + @Override + public List listByLoadBalancerId(long loadBalancerId, + boolean pending) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("revoke", SearchCriteria.Op.EQ, pending); + + return listBy(sc); + } + +} diff --git a/server/src/com/cloud/network/dao/LoadBalancerVMMapVO.java b/server/src/com/cloud/network/dao/LoadBalancerVMMapVO.java index 8856993a982..852302e0949 100644 --- a/server/src/com/cloud/network/dao/LoadBalancerVMMapVO.java +++ b/server/src/com/cloud/network/dao/LoadBalancerVMMapVO.java @@ -39,10 +39,14 @@ public class LoadBalancerVMMapVO implements InternalIdentity { @Column(name="instance_id") private long instanceId; - @Column(name="revoke") + @Column(name = "revoke") private boolean revoke = false; - public LoadBalancerVMMapVO() { } + @Column(name = "state") + private String state; + + public LoadBalancerVMMapVO() { + } public LoadBalancerVMMapVO(long loadBalancerId, long instanceId) { this.loadBalancerId = loadBalancerId; @@ -74,4 +78,12 @@ public class LoadBalancerVMMapVO implements InternalIdentity { public void setRevoke(boolean revoke) { this.revoke = revoke; } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 500d0b68ece..169db3283e3 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.router.CreateVirtualRouterElement import org.apache.cloudstack.api.command.admin.router.ListVirtualRouterElementsCmd; import org.apache.log4j.Logger; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; @@ -363,7 +364,7 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl return true; } } else { - return true; + return false; } } @@ -938,4 +939,11 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl protected VirtualRouterProviderType getVirtualRouterProvider() { return VirtualRouterProviderType.VirtualRouter; } + + @Override + public List updateHealthChecks(Network network, + List lbrules) { + // TODO Auto-generated method stub + return null; + } } diff --git a/server/src/com/cloud/network/lb/LBHealthCheckManager.java b/server/src/com/cloud/network/lb/LBHealthCheckManager.java new file mode 100644 index 00000000000..2e24965aa35 --- /dev/null +++ b/server/src/com/cloud/network/lb/LBHealthCheckManager.java @@ -0,0 +1,24 @@ +// 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. +package com.cloud.network.lb; + + +public interface LBHealthCheckManager { + + void updateLBHealthCheck(); + +} diff --git a/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java b/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java new file mode 100644 index 00000000000..90547328714 --- /dev/null +++ b/server/src/com/cloud/network/lb/LBHealthCheckManagerImpl.java @@ -0,0 +1,110 @@ +// 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. +package com.cloud.network.lb; + +import static java.lang.String.format; + +import java.util.Map; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.component.Manager; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.concurrency.NamedThreadFactory; + +@Component +@Local(value = {LBHealthCheckManager.class}) +public class LBHealthCheckManagerImpl extends ManagerBase implements LBHealthCheckManager, Manager { + private static final Logger s_logger = Logger.getLogger(LBHealthCheckManagerImpl.class); + + @Inject + ConfigurationDao _configDao; + @Inject + LoadBalancingRulesService _lbService; + + private String name; + private Map _configs; + ScheduledExecutorService _executor; + + private long _interval; + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + _configs = _configDao.getConfiguration("management-server", params); + if (s_logger.isInfoEnabled()) { + s_logger.info(format("Configuring LBHealthCheck Manager %1$s", name)); + } + this.name = name; + _interval = NumbersUtil.parseLong(_configs.get(Config.LBHealthCheck.key()), 600); + _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("LBHealthCheck")); + return true; + } + + @Override + public boolean start() { + s_logger.debug("LB HealthCheckmanager is getting Started"); + _executor.scheduleAtFixedRate(new UpdateLBHealthCheck(), 10, _interval, TimeUnit.SECONDS); + return true; + } + + @Override + public boolean stop() { + s_logger.debug("HealthCheckmanager is getting Stopped"); + _executor.shutdown(); + return true; + } + + @Override + public String getName() { + return this.name; + } + + protected class UpdateLBHealthCheck implements Runnable { + @Override + public void run() { + try { + updateLBHealthCheck(); + } catch (Exception e) { + s_logger.error("Exception in LB HealthCheck Update Checker", e); + } + } + } + + @Override + public void updateLBHealthCheck() { + try { + _lbService.updateLBHealthChecks(); + } catch (ResourceUnavailableException e) { + s_logger.debug("Error while updating the LB HealtCheck ", e); + } + s_logger.debug("LB HealthCheck Manager is running and getting the updates from LB providers and updating service status"); + } + +} diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java index 9d7d22fdad7..da19f86c21f 100644 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManager.java @@ -20,6 +20,7 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LbStickinessMethod; @@ -38,6 +39,7 @@ public interface LoadBalancingRulesManager extends LoadBalancingRulesService { List getExistingDestinations(long lbId); List getStickinessPolicies(long lbId); List getStickinessMethods(long networkid); + List getHealthCheckPolicies(long lbId); /** * Remove vm from all load balancers diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 531a42805b6..a06cbc5ca99 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -33,8 +33,11 @@ import javax.inject.Inject; import com.cloud.event.UsageEventUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.ListLBHealthCheckPoliciesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLBStickinessPoliciesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRuleInstancesCmd; import org.apache.cloudstack.api.command.user.loadbalancer.ListLoadBalancerRulesCmd; @@ -42,6 +45,7 @@ import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRul import org.apache.cloudstack.api.response.ServiceResponse; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; @@ -61,6 +65,7 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.ExternalLoadBalancerUsageManager; import com.cloud.network.IpAddress; +import com.cloud.network.LBHealthCheckPolicyVO; import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; @@ -87,6 +92,7 @@ import com.cloud.network.dao.FirewallRulesCidrsDao; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LBHealthCheckPolicyDao; import com.cloud.network.dao.LBStickinessPolicyDao; import com.cloud.network.dao.LBStickinessPolicyVO; import com.cloud.network.dao.LoadBalancerDao; @@ -97,17 +103,20 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.element.LoadBalancingServiceProvider; +import com.cloud.network.element.NetworkElement; import com.cloud.network.lb.LoadBalancingRule.LbAutoScalePolicy; import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmGroup; import com.cloud.network.lb.LoadBalancingRule.LbAutoScaleVmProfile; import com.cloud.network.lb.LoadBalancingRule.LbCondition; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.rules.FirewallManager; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.FirewallRuleType; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.network.rules.LbStickinessMethod; import com.cloud.network.rules.LbStickinessMethod.LbStickinessMethodParam; import com.cloud.network.rules.LoadBalancer; @@ -151,7 +160,8 @@ import com.google.gson.reflect.TypeToken; @Component @Local(value = { LoadBalancingRulesManager.class, LoadBalancingRulesService.class }) -public class LoadBalancingRulesManagerImpl extends ManagerBase implements LoadBalancingRulesManager, LoadBalancingRulesService, NetworkRuleApplier { +public class LoadBalancingRulesManagerImpl extends ManagerBase implements LoadBalancingRulesManager, + LoadBalancingRulesService, NetworkRuleApplier { private static final Logger s_logger = Logger.getLogger(LoadBalancingRulesManagerImpl.class); @Inject @@ -175,6 +185,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Inject LBStickinessPolicyDao _lb2stickinesspoliciesDao; @Inject + LBHealthCheckPolicyDao _lb2healthcheckDao; + @Inject UserVmDao _vmDao; @Inject AccountDao _accountDao; @@ -199,7 +211,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Inject ExternalLoadBalancerUsageManager _externalLBUsageMgr; - @Inject + @Inject NetworkServiceMapDao _ntwkSrvcDao; @Inject ResourceTagDao _resourceTagDao; @@ -229,9 +241,11 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements DataCenterDao _dcDao = null; @Inject UserDao _userDao; - @Inject List _lbProviders; + @Inject + List _lbProviders; - // Will return a string. For LB Stickiness this will be a json, for autoscale this will be "," separated values + // Will return a string. For LB Stickiness this will be a json, for + // autoscale this will be "," separated values @Override public String getLBCapability(long networkid, String capabilityName) { Map> serviceCapabilitiesMap = _networkModel.getNetworkCapabilities(networkid); @@ -240,11 +254,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements ServiceResponse serviceResponse = new ServiceResponse(); serviceResponse.setName(service.getName()); if ("Lb".equalsIgnoreCase(service.getName())) { - Map serviceCapabilities = serviceCapabilitiesMap - .get(service); + Map serviceCapabilities = serviceCapabilitiesMap.get(service); if (serviceCapabilities != null) { - for (Capability capability : serviceCapabilities - .keySet()) { + for (Capability capability : serviceCapabilities.keySet()) { if (capabilityName.equals(capability.getName())) { return serviceCapabilities.get(capability); } @@ -255,14 +267,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } return null; } + private LbAutoScaleVmGroup getLbAutoScaleVmGroup(AutoScaleVmGroupVO vmGroup, String currentState, LoadBalancerVO lb) { long lbNetworkId = lb.getNetworkId(); String lbName = lb.getName(); - List vmGroupPolicyMapList = _autoScaleVmGroupPolicyMapDao.listByVmGroupId(vmGroup.getId()); + List vmGroupPolicyMapList = _autoScaleVmGroupPolicyMapDao.listByVmGroupId(vmGroup + .getId()); List autoScalePolicies = new ArrayList(); for (AutoScaleVmGroupPolicyMapVO vmGroupPolicyMap : vmGroupPolicyMapList) { AutoScalePolicy autoScalePolicy = _autoScalePolicyDao.findById(vmGroupPolicyMap.getPolicyId()); - List autoScalePolicyConditionMapList = _autoScalePolicyConditionMapDao.listByAll(autoScalePolicy.getId(), null); + List autoScalePolicyConditionMapList = _autoScalePolicyConditionMapDao + .listByAll(autoScalePolicy.getId(), null); List lbConditions = new ArrayList(); for (AutoScalePolicyConditionMapVO autoScalePolicyConditionMap : autoScalePolicyConditionMapList) { Condition condition = _conditionDao.findById(autoScalePolicyConditionMap.getConditionId()); @@ -296,32 +311,39 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } } - if (apiKey == null) { - throw new InvalidParameterValueException("apiKey for user: " + user.getUsername() + " is empty. Please generate it"); + throw new InvalidParameterValueException("apiKey for user: " + user.getUsername() + + " is empty. Please generate it"); } if (secretKey == null) { - throw new InvalidParameterValueException("secretKey for user: " + user.getUsername() + " is empty. Please generate it"); + throw new InvalidParameterValueException("secretKey for user: " + user.getUsername() + + " is empty. Please generate it"); } if (csUrl == null || csUrl.contains("localhost")) { - throw new InvalidParameterValueException("Global setting endpointe.url has to be set to the Management Server's API end point"); + throw new InvalidParameterValueException( + "Global setting endpointe.url has to be set to the Management Server's API end point"); } - - LbAutoScaleVmProfile lbAutoScaleVmProfile = new LbAutoScaleVmProfile(autoScaleVmProfile, apiKey, secretKey, csUrl, zoneId, domainId, serviceOfferingId, templateId, vmName, lbNetworkUuid); + LbAutoScaleVmProfile lbAutoScaleVmProfile = new LbAutoScaleVmProfile(autoScaleVmProfile, apiKey, secretKey, + csUrl, zoneId, domainId, serviceOfferingId, templateId, vmName, lbNetworkUuid); return new LbAutoScaleVmGroup(vmGroup, autoScalePolicies, lbAutoScaleVmProfile, currentState); } - private boolean applyAutoScaleConfig(LoadBalancerVO lb, AutoScaleVmGroupVO vmGroup, String currentState) throws ResourceUnavailableException { + private boolean applyAutoScaleConfig(LoadBalancerVO lb, AutoScaleVmGroupVO vmGroup, String currentState) + throws ResourceUnavailableException { LbAutoScaleVmGroup lbAutoScaleVmGroup = getLbAutoScaleVmGroup(vmGroup, currentState, lb); - /* Regular config like destinations need not be packed for applying autoscale config as of today.*/ - LoadBalancingRule rule = new LoadBalancingRule(lb, null, null); + /* + * Regular config like destinations need not be packed for applying + * autoscale config as of today. + */ + LoadBalancingRule rule = new LoadBalancingRule(lb, null, null, null); rule.setAutoScaleVmGroup(lbAutoScaleVmGroup); if (!isRollBackAllowedForProvider(lb)) { - // this is for Netscaler type of devices. if their is failure the db entries will be rollbacked. + // this is for Netscaler type of devices. if their is failure the db + // entries will be rollbacked. return false; } @@ -348,9 +370,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (vmGroup.getState().equals(AutoScaleVmGroup.State_New)) { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); - } - else if (loadBalancer.getState() == FirewallRule.State.Active && - vmGroup.getState().equals(AutoScaleVmGroup.State_Revoke)) { + } else if (loadBalancer.getState() == FirewallRule.State.Active + && vmGroup.getState().equals(AutoScaleVmGroup.State_Revoke)) { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); } @@ -358,11 +379,13 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements try { success = applyAutoScaleConfig(loadBalancer, vmGroup, currentState); } catch (ResourceUnavailableException e) { - s_logger.warn("Unable to configure AutoScaleVmGroup to the lb rule: " + loadBalancer.getId() + " because resource is unavaliable:", e); + s_logger.warn("Unable to configure AutoScaleVmGroup to the lb rule: " + loadBalancer.getId() + + " because resource is unavaliable:", e); if (isRollBackAllowedForProvider(loadBalancer)) { loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); - s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " lb state rolback while creating AutoscaleVmGroup"); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + + " lb state rolback while creating AutoscaleVmGroup"); } throw e; } finally { @@ -387,15 +410,24 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return success; } + private boolean validateHealthCheck(CreateLBHealthCheckPolicyCmd cmd) { + LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); + String capability = getLBCapability(loadBalancer.getNetworkId(), Capability.HealthCheckPolicy.getName()); + if (capability != null) { + return true; + } + return false; + } + private boolean genericValidator(CreateLBStickinessPolicyCmd cmd) throws InvalidParameterValueException { LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); /* Validation : check for valid Method name and params */ - List stickinessMethodList = getStickinessMethods(loadBalancer - .getNetworkId()); + List stickinessMethodList = getStickinessMethods(loadBalancer.getNetworkId()); boolean methodMatch = false; if (stickinessMethodList == null) { - throw new InvalidParameterValueException("Failed: No Stickiness method available for LB rule:" + cmd.getLbRuleId()); + throw new InvalidParameterValueException("Failed: No Stickiness method available for LB rule:" + + cmd.getLbRuleId()); } for (LbStickinessMethod method : stickinessMethodList) { if (method.getMethodName().equalsIgnoreCase(cmd.getStickinessMethodName())) { @@ -422,14 +454,16 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements for (LbStickinessMethodParam param : methodParamList) { if (param.getParamName().equalsIgnoreCase(paramName)) { if ((param.getIsflag() == false) && (paramValue == null)) { - throw new InvalidParameterValueException("Failed : Value expected for the Param :" + param.getParamName()); + throw new InvalidParameterValueException("Failed : Value expected for the Param :" + + param.getParamName()); } found = true; break; } } if (!found) { - throw new InvalidParameterValueException("Failed : Stickiness policy does not support param name :" + paramName); + throw new InvalidParameterValueException( + "Failed : Stickiness policy does not support param name :" + paramName); } } } @@ -438,7 +472,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements for (LbStickinessMethodParam param : methodParamList) { if (param.getRequired()) { if (tempParamList.get(param.getParamName()) == null) { - throw new InvalidParameterValueException("Failed : Missing Manadatory Param :" + param.getParamName()); + throw new InvalidParameterValueException("Failed : Missing Manadatory Param :" + + param.getParamName()); } } } @@ -447,13 +482,16 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } } if (methodMatch == false) { - throw new InvalidParameterValueException("Failed to match Stickiness method name for LB rule:" + cmd.getLbRuleId()); + throw new InvalidParameterValueException("Failed to match Stickiness method name for LB rule:" + + cmd.getLbRuleId()); } /* Validation : check for the multiple policies to the rule id */ - List stickinessPolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(cmd.getLbRuleId(), false); + List stickinessPolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId( + cmd.getLbRuleId(), false); if (stickinessPolicies.size() > 0) { - throw new InvalidParameterValueException("Failed to create Stickiness policy: Already policy attached " + cmd.getLbRuleId()); + throw new InvalidParameterValueException("Failed to create Stickiness policy: Already policy attached " + + cmd.getLbRuleId()); } return true; } @@ -462,7 +500,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override @DB @ActionEvent(eventType = EventTypes.EVENT_LB_STICKINESSPOLICY_CREATE, eventDescription = "create lb stickinesspolicy to load balancer", create = true) - public StickinessPolicy createLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd) throws NetworkRuleConflictException { + public StickinessPolicy createLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd) + throws NetworkRuleConflictException { UserContext caller = UserContext.current(); /* Validation : check corresponding load balancer rule exist */ @@ -473,30 +512,108 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements _accountMgr.checkAccess(caller.getCaller(), null, true, loadBalancer); if (loadBalancer.getState() == FirewallRule.State.Revoke) { - throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " is in deleting state: "); + throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + + " is in deleting state: "); } /* Generic validations */ if (!genericValidator(cmd)) { - throw new InvalidParameterValueException("Failed to create Stickiness policy: Validation Failed " + cmd.getLbRuleId()); + throw new InvalidParameterValueException("Failed to create Stickiness policy: Validation Failed " + + cmd.getLbRuleId()); } - /* Specific validations using network element validator for specific validations */ - LBStickinessPolicyVO lbpolicy = new LBStickinessPolicyVO(loadBalancer.getId(), cmd.getLBStickinessPolicyName(), cmd.getStickinessMethodName(), cmd.getparamList(), cmd.getDescription()); + /* + * Specific validations using network element validator for specific + * validations + */ + LBStickinessPolicyVO lbpolicy = new LBStickinessPolicyVO(loadBalancer.getId(), cmd.getLBStickinessPolicyName(), + cmd.getStickinessMethodName(), cmd.getparamList(), cmd.getDescription()); List policyList = new ArrayList(); policyList.add(new LbStickinessPolicy(cmd.getStickinessMethodName(), lbpolicy.getParams())); - LoadBalancingRule lbRule = new LoadBalancingRule(loadBalancer, getExistingDestinations(lbpolicy.getId()), policyList); + LoadBalancingRule lbRule = new LoadBalancingRule(loadBalancer, getExistingDestinations(lbpolicy.getId()), + policyList, null); if (!validateRule(lbRule)) { - throw new InvalidParameterValueException("Failed to create Stickiness policy: Validation Failed " + cmd.getLbRuleId()); + throw new InvalidParameterValueException("Failed to create Stickiness policy: Validation Failed " + + cmd.getLbRuleId()); } /* Finally Insert into DB */ - LBStickinessPolicyVO policy = new LBStickinessPolicyVO(loadBalancer.getId(), cmd.getLBStickinessPolicyName(), cmd.getStickinessMethodName(), cmd.getparamList(), cmd.getDescription()); + LBStickinessPolicyVO policy = new LBStickinessPolicyVO(loadBalancer.getId(), cmd.getLBStickinessPolicyName(), + cmd.getStickinessMethodName(), cmd.getparamList(), cmd.getDescription()); policy = _lb2stickinesspoliciesDao.persist(policy); return policy; } + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_LB_HEALTHCHECKPOLICY_CREATE, eventDescription = "create load balancer health check to load balancer", create = true) + public HealthCheckPolicy createLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd cmd) { + UserContext caller = UserContext.current(); + + /* + * Validation of cmd Monitor interval must be greater than response + * timeout + */ + Map paramMap = cmd.getFullUrlParams(); + + if (paramMap.containsKey(ApiConstants.HEALTHCHECK_RESPONSE_TIMEOUT) + && paramMap.containsKey(ApiConstants.HEALTHCHECK_INTERVAL_TIME)) { + if (cmd.getResponsTimeOut() > cmd.getHealthCheckInterval()) + throw new InvalidParameterValueException( + "Failed to create HealthCheck policy : Monitor interval must be greater than response timeout"); + } + /* Validation : check corresponding load balancer rule exist */ + LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); + if (loadBalancer == null) { + throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " not present "); + } + + _accountMgr.checkAccess(caller.getCaller(), null, true, loadBalancer); + + if (loadBalancer.getState() == FirewallRule.State.Revoke) { + throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + + " is in deleting state: "); + } + + /* + * Validate Whether LB Provider has the capabilities to support Health + * Checks + */ + if (!validateHealthCheck(cmd)) { + throw new InvalidParameterValueException( + "Failed to create HealthCheck policy: Validation Failed (HealthCheck Policy is not supported by LB Provider for the LB rule id :)" + + cmd.getLbRuleId()); + } + + /* Validation : check for the multiple hc policies to the rule id */ + List hcPolicies = _lb2healthcheckDao.listByLoadBalancerId(cmd.getLbRuleId(), false); + if (hcPolicies.size() > 0) { + throw new InvalidParameterValueException( + "Failed to create HealthCheck policy: Already policy attached for the LB Rule id :" + + cmd.getLbRuleId()); + } + /* + * Specific validations using network element validator for specific + * validations + */ + LBHealthCheckPolicyVO hcpolicy = new LBHealthCheckPolicyVO(loadBalancer.getId(), cmd.getPingPath(), + cmd.getDescription(), cmd.getResponsTimeOut(), cmd.getHealthCheckInterval(), cmd.getHealthyThreshold(), + cmd.getUnhealthyThreshold()); + + List hcPolicyList = new ArrayList(); + hcPolicyList.add(new LbHealthCheckPolicy(hcpolicy.getpingpath(), hcpolicy.getDescription(), hcpolicy + .getResponseTime(), hcpolicy.getHealthcheckInterval(), hcpolicy.getHealthcheckThresshold(), hcpolicy + .getUnhealthThresshold())); + + // Finally Insert into DB + LBHealthCheckPolicyVO policy = new LBHealthCheckPolicyVO(loadBalancer.getId(), cmd.getPingPath(), + cmd.getDescription(), cmd.getResponsTimeOut(), cmd.getHealthCheckInterval(), cmd.getHealthyThreshold(), + cmd.getUnhealthyThreshold()); + + policy = _lb2healthcheckDao.persist(policy); + return policy; + } private boolean validateRule(LoadBalancingRule lbRule) { Network network = _networkDao.findById(lbRule.getNetworkId()); @@ -506,7 +623,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return false; } for (LoadBalancingServiceProvider ne : _lbProviders) { - boolean validated = ne.validateLBRule(network, lbRule); + boolean validated = ne.validateLBRule(network, lbRule); if (!validated) return false; } @@ -521,7 +638,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); if (loadBalancer == null) { - throw new InvalidParameterException("Invalid Load balancer Id:" + cmd.getLbRuleId()); + throw new InvalidParameterException("Invalid Load balancer Id:" + cmd.getLbRuleId()); } FirewallRule.State backupState = loadBalancer.getState(); loadBalancer.setState(FirewallRule.State.Add); @@ -529,11 +646,13 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements try { applyLoadBalancerConfig(cmd.getLbRuleId()); } catch (ResourceUnavailableException e) { - s_logger.warn("Unable to apply Stickiness policy to the lb rule: " + cmd.getLbRuleId() + " because resource is unavaliable:", e); + s_logger.warn("Unable to apply Stickiness policy to the lb rule: " + cmd.getLbRuleId() + + " because resource is unavaliable:", e); if (isRollBackAllowedForProvider(loadBalancer)) { loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); - s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " lb state rolback while creating sticky policy"); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + + " lb state rolback while creating sticky policy"); } deleteLBStickinessPolicy(cmd.getEntityId(), false); success = false; @@ -542,6 +661,36 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return success; } + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_LB_HEALTHCHECKPOLICY_CREATE, eventDescription = "Apply HealthCheckPolicy to load balancer ", async = true) + public boolean applyLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd cmd) { + boolean success = true; + + LoadBalancerVO loadBalancer = _lbDao.findById(cmd.getLbRuleId()); + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid Load balancer Id:" + cmd.getLbRuleId()); + } + FirewallRule.State backupState = loadBalancer.getState(); + loadBalancer.setState(FirewallRule.State.Add); + _lbDao.persist(loadBalancer); + try { + applyLoadBalancerConfig(cmd.getLbRuleId()); + } catch (ResourceUnavailableException e) { + s_logger.warn("Unable to apply healthcheck policy to the lb rule: " + cmd.getLbRuleId() + + " because resource is unavaliable:", e); + if (isRollBackAllowedForProvider(loadBalancer)) { + loadBalancer.setState(backupState); + _lbDao.persist(loadBalancer); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + + " lb state rolback while creating healthcheck policy"); + } + deleteLBHealthCheckPolicy(cmd.getEntityId(), false); + success = false; + } + return success; + } + @Override @ActionEvent(eventType = EventTypes.EVENT_LB_STICKINESSPOLICY_DELETE, eventDescription = "revoking LB Stickiness policy ", async = true) public boolean deleteLBStickinessPolicy(long stickinessPolicyId, boolean apply) { @@ -555,13 +704,13 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(stickinessPolicy.getLoadBalancerId())); if (loadBalancer == null) { - throw new InvalidParameterException("Invalid Load balancer : " + stickinessPolicy.getLoadBalancerId() + " for Stickiness policy id: " + stickinessPolicyId); + throw new InvalidParameterException("Invalid Load balancer : " + stickinessPolicy.getLoadBalancerId() + + " for Stickiness policy id: " + stickinessPolicyId); } long loadBalancerId = loadBalancer.getId(); FirewallRule.State backupState = loadBalancer.getState(); _accountMgr.checkAccess(caller.getCaller(), null, true, loadBalancer); - if (apply) { if (loadBalancer.getState() == FirewallRule.State.Active) { loadBalancer.setState(FirewallRule.State.Add); @@ -571,12 +720,15 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements boolean backupStickyState = stickinessPolicy.isRevoke(); stickinessPolicy.setRevoke(true); _lb2stickinesspoliciesDao.persist(stickinessPolicy); - s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", stickinesspolicyID " + stickinessPolicyId); + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", stickinesspolicyID " + + stickinessPolicyId); try { if (!applyLoadBalancerConfig(loadBalancerId)) { - s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + " for stickinesspolicyID " + stickinessPolicyId); - throw new CloudRuntimeException("Failed to remove load balancer rule id " + loadBalancerId + " for stickinesspolicyID " + stickinessPolicyId); + s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + + " for stickinesspolicyID " + stickinessPolicyId); + throw new CloudRuntimeException("Failed to remove load balancer rule id " + loadBalancerId + + " for stickinesspolicyID " + stickinessPolicyId); } } catch (ResourceUnavailableException e) { if (isRollBackAllowedForProvider(loadBalancer)) { @@ -584,7 +736,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements _lb2stickinesspoliciesDao.persist(stickinessPolicy); loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); - s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " while deleting sticky policy: " + stickinessPolicyId); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " while deleting sticky policy: " + + stickinessPolicyId); } s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); success = false; @@ -592,9 +745,149 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } else { _lb2stickinesspoliciesDao.remove(stickinessPolicy.getLoadBalancerId()); } - return success; - } + } + + @DB + @Override + @ActionEvent(eventType = EventTypes.EVENT_LB_HEALTHCHECKPOLICY_DELETE, eventDescription = "revoking LB HealthCheck policy ", async = true) + public boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply) { + boolean success = true; + + UserContext caller = UserContext.current(); + LBHealthCheckPolicyVO healthCheckPolicy = _lb2healthcheckDao.findById(healthCheckPolicyId); + + if (healthCheckPolicy == null) { + throw new InvalidParameterException("Invalid HealthCheck policy id value: " + healthCheckPolicyId); + } + LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(healthCheckPolicy.getLoadBalancerId())); + if (loadBalancer == null) { + throw new InvalidParameterException("Invalid Load balancer : " + healthCheckPolicy.getLoadBalancerId() + + " for HealthCheck policy id: " + healthCheckPolicyId); + } + long loadBalancerId = loadBalancer.getId(); + FirewallRule.State backupState = loadBalancer.getState(); + _accountMgr.checkAccess(caller.getCaller(), null, true, loadBalancer); + + if (apply) { + if (loadBalancer.getState() == FirewallRule.State.Active) { + loadBalancer.setState(FirewallRule.State.Add); + _lbDao.persist(loadBalancer); + } + + boolean backupStickyState = healthCheckPolicy.isRevoke(); + healthCheckPolicy.setRevoke(true); + _lb2healthcheckDao.persist(healthCheckPolicy); + s_logger.debug("Set health check policy to revoke for loadbalancing rule id : " + loadBalancerId + + ", healthCheckpolicyID " + healthCheckPolicyId); + + // removing the state of services set by the monitor. + List maps = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId); + if (maps != null) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + s_logger.debug("Resetting health state policy for services in loadbalancing rule id : " + + loadBalancerId); + for (LoadBalancerVMMapVO map : maps) { + map.setState(null); + _lb2VmMapDao.persist(map); + } + txn.commit(); + } + + try { + if (!applyLoadBalancerConfig(loadBalancerId)) { + s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + + " for healthCheckpolicyID " + healthCheckPolicyId); + throw new CloudRuntimeException("Failed to remove load balancer rule id " + loadBalancerId + + " for healthCheckpolicyID " + healthCheckPolicyId); + } + } catch (ResourceUnavailableException e) { + if (isRollBackAllowedForProvider(loadBalancer)) { + healthCheckPolicy.setRevoke(backupStickyState); + _lb2healthcheckDao.persist(healthCheckPolicy); + loadBalancer.setState(backupState); + _lbDao.persist(loadBalancer); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + + " while deleting healthcheck policy: " + healthCheckPolicyId); + } + s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); + success = false; + } + } else { + _lb2healthcheckDao.remove(healthCheckPolicy.getLoadBalancerId()); + } + return success; + } + + // This method will check the status of services which has monitors created + // by CloudStack and update them in lbvmmap table + @DB + @Override + public void updateLBHealthChecks() throws ResourceUnavailableException { + List rules = _lbDao.listAll(); + List networks = _networkDao.listAll(); + List stateRules = null; + boolean isHandled = false; + for (NetworkVO ntwk : networks) { + Network network = _networkDao.findById(ntwk.getId()); + String capability = getLBCapability(network.getId(), Capability.HealthCheckPolicy.getName()); + + if (capability != null && capability.equalsIgnoreCase("true")) { + /* + * s_logger.debug( + * "HealthCheck Manager :: LB Provider in the Network has the Healthcheck policy capability :: " + * + provider.get(0).getName()); + */ + rules = _lbDao.listByNetworkId(network.getId()); + if (rules != null && rules.size() > 0) { + List lbrules = new ArrayList(); + for (LoadBalancerVO lb : rules) { + List dstList = getExistingDestinations(lb.getId()); + List hcPolicyList = getHealthCheckPolicies(lb.getId()); + // adding to lbrules list only if the LB rule + // hashealtChecks + if (hcPolicyList != null && hcPolicyList.size() > 0) { + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, null, hcPolicyList); + lbrules.add(loadBalancing); + } + } + if (lbrules.size() > 0) { + isHandled = false; + for (LoadBalancingServiceProvider lbElement : _lbProviders) { + stateRules = lbElement.updateHealthChecks(network, (List) lbrules); + if (stateRules != null && stateRules.size() > 0) { + for (LoadBalancerTO lbto : stateRules) { + LoadBalancerVO ulb = _lbDao.findByUuid(lbto.getUuid()); + List lbVmMaps = _lb2VmMapDao.listByLoadBalancerId(ulb.getId()); + for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { + UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); + Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved( + ulb.getNetworkId(), vm.getId()); + String dstIp = nic.getIp4Address(); + for (int i = 0; i < lbto.getDestinations().length; i++) { + LoadBalancerTO.DestinationTO des = lbto.getDestinations()[i]; + if (dstIp.equalsIgnoreCase(lbto.getDestinations()[i].getDestIp())) { + lbVmMap.setState(des.getMonitorState()); + _lb2VmMapDao.persist(lbVmMap); + s_logger.debug("Updating the LB VM Map table with the service state"); + } + } + } + } + isHandled = true; + } + if (isHandled) { + break; + } + } + } + } + } else { + // s_logger.debug("HealthCheck Manager :: LB Provider in the Network DNOT the Healthcheck policy capability "); + } + } + } private boolean isRollBackAllowedForProvider(LoadBalancerVO loadBalancer) { Network network = _networkDao.findById(loadBalancer.getNetworkId()); @@ -607,6 +900,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } return false; } + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true) @@ -616,7 +910,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); if (loadBalancer == null) { - throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found."); + throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + + ", the load balancer was not found."); } List mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false); @@ -635,7 +930,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { InvalidParameterValueException ex = new InvalidParameterValueException("Invalid instance id specified"); - ex.addProxyObject(vm, instanceId, "instanceId"); + ex.addProxyObject(vm, instanceId, "instanceId"); throw ex; } @@ -645,7 +940,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements throw new PermissionDeniedException("Cannot add virtual machines that do not belong to the same owner."); } - // Let's check to make sure the vm has a nic in the same network as the load balancing rule. + // Let's check to make sure the vm has a nic in the same network as + // the load balancing rule. List nics = _networkModel.getNics(vm.getId()); Nic nicInSameNetwork = null; for (Nic nic : nics) { @@ -656,8 +952,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } if (nicInSameNetwork == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("VM " + instanceId + " cannot be added because it doesn't belong in the same network."); - ex.addProxyObject(vm, instanceId, "instanceId"); + InvalidParameterValueException ex = new InvalidParameterValueException("VM " + instanceId + + " cannot be added because it doesn't belong in the same network."); + ex.addProxyObject(vm, instanceId, "instanceId"); throw ex; } @@ -698,7 +995,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements txn.commit(); if (!vmInstanceIds.isEmpty()) { _lb2VmMapDao.remove(loadBalancer.getId(), vmInstanceIds, null); - s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " while attaching VM: " + vmInstanceIds); + s_logger.debug("LB Rollback rule id: " + loadBalancer.getId() + " while attaching VM: " + + vmInstanceIds); } loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); @@ -707,9 +1005,11 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); - // TBD: Also pack in the instanceIds in the exception using the right VO object or table name. + CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + + instanceIds); + ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + // TBD: Also pack in the instanceIds in the exception using the + // right VO object or table name. throw ex; } @@ -748,15 +1048,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(loadBalancerId)) { // For autoscaled loadbalancer, the rules need not be applied, // meaning the call need not reach the resource layer. - // We can consider the job done and only need to remove the rules in DB + // We can consider the job done and only need to remove the + // rules in DB _lb2VmMapDao.remove(loadBalancer.getId(), instanceIds, null); return true; } if (!applyLoadBalancerConfig(loadBalancerId)) { s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds); - CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to remove specified load balancer rule id for vms " + instanceIds); + ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); throw ex; } success = true; @@ -777,8 +1079,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); } if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to remove specified load balancer rule id for vms " + instanceIds); + ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); throw ex; } return success; @@ -806,7 +1109,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements map.setRevoke(true); _lb2VmMapDao.persist(map); - s_logger.debug("Set load balancer rule for revoke: rule id " + map.getLoadBalancerId() + ", vmId " + instanceId); + s_logger.debug("Set load balancer rule for revoke: rule id " + map.getLoadBalancerId() + ", vmId " + + instanceId); } // Reapply all lbs that had the vm assigned @@ -827,10 +1131,10 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements Account caller = ctx.getCaller(); LoadBalancerVO rule = _lbDao.findById(loadBalancerId); + if (rule == null) { throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId); } - _accountMgr.checkAccess(caller, null, true, rule); boolean result = deleteLoadBalancerRule(loadBalancerId, apply, caller, ctx.getCallerUserId(), true); @@ -841,7 +1145,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } @DB - public boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply, Account caller, long callerUserId, boolean rollBack) { + public boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply, Account caller, long callerUserId, + boolean rollBack) { LoadBalancerVO lb = _lbDao.findById(loadBalancerId); Transaction txn = Transaction.currentTxn(); boolean generateUsageEvent = false; @@ -865,10 +1170,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements for (LoadBalancerVMMapVO map : maps) { map.setRevoke(true); _lb2VmMapDao.persist(map); - s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + map.getInstanceId()); + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + + map.getInstanceId()); } } + List hcPolicies = _lb2healthcheckDao.listByLoadBalancerId(loadBalancerId); + for (LBHealthCheckPolicyVO lbHealthCheck : hcPolicies) { + lbHealthCheck.setRevoke(true); + _lb2healthcheckDao.persist(lbHealthCheck); + } + if (generateUsageEvent) { // Generate usage event right after all rules were marked for revoke UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_DELETE, lb.getAccountId(), 0, lb.getId(), @@ -890,7 +1202,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(loadBalancerId)) { // Get the associated VmGroup AutoScaleVmGroupVO vmGroup = _autoScaleVmGroupDao.listByAll(loadBalancerId, null).get(0); - if (!applyAutoScaleConfig(lb, vmGroup,vmGroup.getState())) { + if (!applyAutoScaleConfig(lb, vmGroup, vmGroup.getState())) { s_logger.warn("Unable to apply the autoscale config"); return false; } @@ -920,15 +1232,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements FirewallRuleVO relatedRule = _firewallDao.findByRelatedId(lb.getId()); if (relatedRule != null) { - s_logger.warn("Unable to remove firewall rule id=" + lb.getId() + " as it has related firewall rule id=" + relatedRule.getId() + "; leaving it in Revoke state"); + s_logger.warn("Unable to remove firewall rule id=" + lb.getId() + " as it has related firewall rule id=" + + relatedRule.getId() + "; leaving it in Revoke state"); success = false; } else { _firewallMgr.removeRule(lb); } - // FIXME: breaking the dependency on ELB manager. This breaks functionality of ELB using virtual router + // FIXME: breaking the dependency on ELB manager. This breaks + // functionality of ELB using virtual router // Bug CS-15411 opened to document this - //_elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller); + // _elbMgr.handleDeleteLoadBalancerRule(lb, callerUserId, caller); if (success) { s_logger.debug("Load balancer with id " + lb.getId() + " is removed successfully"); @@ -939,7 +1253,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override @ActionEvent(eventType = EventTypes.EVENT_LOAD_BALANCER_CREATE, eventDescription = "creating load balancer") - public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb, boolean openFirewall) throws NetworkRuleConflictException, InsufficientAddressCapacityException { + public LoadBalancer createLoadBalancerRule(CreateLoadBalancerRuleCmd lb, boolean openFirewall) + throws NetworkRuleConflictException, InsufficientAddressCapacityException { Account lbOwner = _accountMgr.getAccount(lb.getEntityOwnerId()); int defPortStart = lb.getDefaultPortStart(); @@ -949,7 +1264,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements throw new InvalidParameterValueException("privatePort is an invalid value: " + defPortEnd); } if (defPortStart > defPortEnd) { - throw new InvalidParameterValueException("private port range is invalid: " + defPortStart + "-" + defPortEnd); + throw new InvalidParameterValueException("private port range is invalid: " + defPortStart + "-" + + defPortEnd); } if ((lb.getAlgorithm() == null) || !NetUtils.isValidAlgorithm(lb.getAlgorithm())) { throw new InvalidParameterValueException("Invalid algorithm: " + lb.getAlgorithm()); @@ -963,9 +1279,11 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements Network network = _networkModel.getNetwork(lb.getNetworkId()); - // FIXME: breaking the dependency on ELB manager. This breaks functionality of ELB using virtual router + // FIXME: breaking the dependency on ELB manager. This breaks + // functionality of ELB using virtual router // Bug CS-15411 opened to document this - //LoadBalancer result = _elbMgr.handleCreateLoadBalancerRule(lb, lbOwner, lb.getNetworkId()); + // LoadBalancer result = _elbMgr.handleCreateLoadBalancerRule(lb, + // lbOwner, lb.getNetworkId()); LoadBalancer result = null; if (result == null) { IpAddress systemIp = null; @@ -978,7 +1296,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements // Validate ip address if (ipVO == null) { - throw new InvalidParameterValueException("Unable to create load balance rule; can't find/allocate source IP"); + throw new InvalidParameterValueException( + "Unable to create load balance rule; can't find/allocate source IP"); } else if (ipVO.isOneToOneNat()) { throw new NetworkRuleConflictException("Can't do load balance on ip address: " + ipVO.getAddress()); } @@ -986,13 +1305,14 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements boolean performedIpAssoc = false; try { if (ipVO.getAssociatedWithNetworkId() == null) { - boolean assignToVpcNtwk = network.getVpcId() != null - && ipVO.getVpcId() != null && ipVO.getVpcId().longValue() == network.getVpcId(); + boolean assignToVpcNtwk = network.getVpcId() != null && ipVO.getVpcId() != null + && ipVO.getVpcId().longValue() == network.getVpcId(); if (assignToVpcNtwk) { - //set networkId just for verification purposes + // set networkId just for verification purposes _networkModel.checkIpForService(ipVO, Service.Lb, lb.getNetworkId()); - s_logger.debug("The ip is not associated with the VPC network id="+ lb.getNetworkId() + " so assigning"); + s_logger.debug("The ip is not associated with the VPC network id=" + lb.getNetworkId() + + " so assigning"); ipVO = _networkMgr.associateIPToGuestNetwork(ipAddrId, lb.getNetworkId(), false); performedIpAssoc = true; } @@ -1000,8 +1320,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements _networkModel.checkIpForService(ipVO, Service.Lb, null); } - if (ipVO.getAssociatedWithNetworkId() == null) { - throw new InvalidParameterValueException("Ip address " + ipVO + " is not assigned to the network " + network); + if (ipVO.getAssociatedWithNetworkId() == null) { + throw new InvalidParameterValueException("Ip address " + ipVO + " is not assigned to the network " + + network); } if (lb.getSourceIpAddressId() == null) { @@ -1015,7 +1336,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } } finally { if (result == null && systemIp != null) { - s_logger.debug("Releasing system IP address " + systemIp + " as corresponding lb rule failed to create"); + s_logger.debug("Releasing system IP address " + systemIp + + " as corresponding lb rule failed to create"); _networkMgr.handleSystemIpRelease(systemIp); } // release ip address if ipassoc was perfored @@ -1035,7 +1357,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override @DB - public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb, boolean openFirewall) throws NetworkRuleConflictException { + public LoadBalancer createLoadBalancer(CreateLoadBalancerRuleCmd lb, boolean openFirewall) + throws NetworkRuleConflictException { UserContext caller = UserContext.current(); int srcPortStart = lb.getSourcePortStart(); int defPortStart = lb.getDefaultPortStart(); @@ -1045,45 +1368,48 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements IPAddressVO ipAddr = _ipAddressDao.findById(sourceIpId); // make sure ip address exists if (ipAddr == null || !ipAddr.readyToUse()) { - InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule, invalid IP address id specified"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Unable to create load balancer rule, invalid IP address id specified"); + ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); throw ex; } else if (ipAddr.isOneToOneNat()) { - InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule; specified sourceip id has static nat enabled"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Unable to create load balancer rule; specified sourceip id has static nat enabled"); + ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); throw ex; } Long networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Unable to create load balancer rule ; specified sourceip id is not associated with any network"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Unable to create load balancer rule ; specified sourceip id is not associated with any network"); + ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); throw ex; - } _firewallMgr.validateFirewallRule(caller.getCaller(), ipAddr, srcPortStart, srcPortEnd, lb.getProtocol(), Purpose.LoadBalancing, FirewallRuleType.User, networkId, null); - NetworkVO network = _networkDao.findById(networkId); - _accountMgr.checkAccess(caller.getCaller(), null, true, ipAddr); // verify that lb service is supported by the network if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { - InvalidParameterValueException ex = new InvalidParameterValueException("LB service is not supported in specified network id"); - ex.addProxyObject(network, networkId, "networkId"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "LB service is not supported in specified network id"); + ex.addProxyObject(network, networkId, "networkId"); throw ex; } Transaction txn = Transaction.currentTxn(); txn.start(); - LoadBalancerVO newRule = new LoadBalancerVO(lb.getXid(), lb.getName(), lb.getDescription(), lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(), - lb.getAlgorithm(), network.getId(), ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId()); + LoadBalancerVO newRule = new LoadBalancerVO(lb.getXid(), lb.getName(), lb.getDescription(), + lb.getSourceIpAddressId(), lb.getSourcePortEnd(), lb.getDefaultPortStart(), lb.getAlgorithm(), + network.getId(), ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId()); // verify rule is supported by Lb provider of the network - LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList(), new ArrayList()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(newRule, new ArrayList(), + new ArrayList(), new ArrayList()); if (!validateRule(loadBalancing)) { throw new InvalidParameterValueException("LB service provider cannot support this rule"); } @@ -1091,7 +1417,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements newRule = _lbDao.persist(newRule); if (openFirewall) { - _firewallMgr.createRuleForAllCidrs(sourceIpId, caller.getCaller(), lb.getSourcePortStart(), + _firewallMgr.createRuleForAllCidrs(sourceIpId, caller.getCaller(), lb.getSourcePortStart(), lb.getSourcePortEnd(), lb.getProtocol(), null, null, newRule.getId(), networkId); } @@ -1102,10 +1428,12 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!_firewallDao.setStateToAdd(newRule)) { throw new CloudRuntimeException("Unable to update the state to add for " + newRule); } - s_logger.debug("Load balancer " + newRule.getId() + " for Ip address id=" + sourceIpId + ", public port " + srcPortStart + ", private port " + defPortStart + " is added successfully."); + s_logger.debug("Load balancer " + newRule.getId() + " for Ip address id=" + sourceIpId + ", public port " + + srcPortStart + ", private port " + defPortStart + " is added successfully."); UserContext.current().setEventDetails("Load balancer Id: " + newRule.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_LOAD_BALANCER_CREATE, ipAddr.getAllocatedToAccountId(), - ipAddr.getDataCenterId(), newRule.getId(), null, LoadBalancingRule.class.getName(), newRule.getUuid()); + ipAddr.getDataCenterId(), newRule.getId(), null, LoadBalancingRule.class.getName(), + newRule.getUuid()); txn.commit(); return newRule; @@ -1131,8 +1459,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements public boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException { LoadBalancerVO lb = _lbDao.findById(lbRuleId); List lbs; - if (isRollBackAllowedForProvider(lb)) { - // this is for Netscalar type of devices. if their is failure the db entries will be rollbacked. + if (isRollBackAllowedForProvider(lb)) { + // this is for Netscalar type of devices. if their is failure the db + // entries will be rollbacked. lbs = Arrays.asList(lb); } else { // get all rules in transition state @@ -1153,13 +1482,14 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } @Override - public boolean applyRules(Network network, Purpose purpose, List rules) + public boolean applyRules(Network network, Purpose purpose, List rules) throws ResourceUnavailableException { - assert(purpose == Purpose.LoadBalancing): "LB Manager asked to handle non-LB rules"; + assert (purpose == Purpose.LoadBalancing) : "LB Manager asked to handle non-LB rules"; boolean handled = false; - for (LoadBalancingServiceProvider lbElement: _lbProviders) { + for (LoadBalancingServiceProvider lbElement : _lbProviders) { Provider provider = lbElement.getProvider(); - boolean isLbProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Lb, provider); + boolean isLbProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Lb, + provider); if (!isLbProvider) { continue; } @@ -1171,14 +1501,16 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } @DB - protected boolean applyLoadBalancerRules(List lbs, boolean updateRulesInDB) throws ResourceUnavailableException { + protected boolean applyLoadBalancerRules(List lbs, boolean updateRulesInDB) + throws ResourceUnavailableException { Transaction txn = Transaction.currentTxn(); List rules = new ArrayList(); for (LoadBalancerVO lb : lbs) { List dstList = getExistingDestinations(lb.getId()); List policyList = getStickinessPolicies(lb.getId()); + List hcPolicyList = getHealthCheckPolicies(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); rules.add(loadBalancing); } @@ -1217,18 +1549,28 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (_lb2VmMapDao.listByLoadBalancerId(lb.getId()).isEmpty()) { lb.setState(FirewallRule.State.Add); _lbDao.persist(lb); - s_logger.debug("LB rule " + lb.getId() + " state is set to Add as there are no more active LB-VM mappings"); + s_logger.debug("LB rule " + lb.getId() + + " state is set to Add as there are no more active LB-VM mappings"); } // remove LB-Stickiness policy mapping that were state to revoke - List stickinesspolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(lb.getId(), true); + List stickinesspolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId( + lb.getId(), true); if (!stickinesspolicies.isEmpty()) { _lb2stickinesspoliciesDao.remove(lb.getId(), true); s_logger.debug("Load balancer rule id " + lb.getId() + " is removed stickiness policies"); } - txn.commit(); + // remove LB-HealthCheck policy mapping that were state to + // revoke + List healthCheckpolicies = _lb2healthcheckDao.listByLoadBalancerId(lb.getId(), + true); + if (!healthCheckpolicies.isEmpty()) { + _lb2healthcheckDao.remove(lb.getId(), true); + s_logger.debug("Load balancer rule id " + lb.getId() + " is removed health check monitors policies"); + } + txn.commit(); if (checkForReleaseElasticIp) { boolean success = true; long count = _firewallDao.countRulesByIpId(lb.getSourceIpAddressId()); @@ -1236,7 +1578,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements try { success = handleSystemLBIpRelease(lb); } catch (Exception ex) { - s_logger.warn("Failed to release system ip as a part of lb rule " + lb + " deletion due to exception ", ex); + s_logger.warn("Failed to release system ip as a part of lb rule " + lb + + " deletion due to exception ", ex); success = false; } finally { if (!success) { @@ -1245,7 +1588,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } } } - // if the rule is the last one for the ip address assigned to VPC, unassign it from the network + // if the rule is the last one for the ip address assigned to + // VPC, unassign it from the network IpAddress ip = _ipAddressDao.findById(lb.getSourceIpAddressId()); _vpcMgr.unassignIPFromVpcNetwork(ip.getId(), lb.getNetworkId()); } @@ -1259,14 +1603,16 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements boolean success = true; if (ip.getSystem()) { s_logger.debug("Releasing system ip address " + lb.getSourceIpAddressId() + " as a part of delete lb rule"); - if (!_networkMgr.disassociatePublicIpAddress(lb.getSourceIpAddressId(), UserContext.current().getCallerUserId(), UserContext.current().getCaller())) { - s_logger.warn("Unable to release system ip address id=" + lb.getSourceIpAddressId() + " as a part of delete lb rule"); + if (!_networkMgr.disassociatePublicIpAddress(lb.getSourceIpAddressId(), UserContext.current() + .getCallerUserId(), UserContext.current().getCaller())) { + s_logger.warn("Unable to release system ip address id=" + lb.getSourceIpAddressId() + + " as a part of delete lb rule"); success = false; } else { - s_logger.warn("Successfully released system ip address id=" + lb.getSourceIpAddressId() + " as a part of delete lb rule"); + s_logger.warn("Successfully released system ip address id=" + lb.getSourceIpAddressId() + + " as a part of delete lb rule"); } } - return success; } @@ -1287,7 +1633,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Override public boolean removeAllLoadBalanacersForNetwork(long networkId, Account caller, long callerUserId) { - List rules = _firewallDao.listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.LoadBalancing); + List rules = _firewallDao + .listByNetworkAndPurposeAndNotRevoked(networkId, Purpose.LoadBalancing); if (rules != null) s_logger.debug("Found " + rules.size() + " lb rules to cleanup"); for (FirewallRule rule : rules) { @@ -1306,12 +1653,28 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(lbId); for (LBStickinessPolicyVO sDbPolicy : sDbpolicies) { - LbStickinessPolicy sPolicy = new LbStickinessPolicy(sDbPolicy.getMethodName(), sDbPolicy.getParams(), sDbPolicy.isRevoke()); + LbStickinessPolicy sPolicy = new LbStickinessPolicy(sDbPolicy.getMethodName(), sDbPolicy.getParams(), + sDbPolicy.isRevoke()); stickinessPolicies.add(sPolicy); } return stickinessPolicies; } + @Override + public List getHealthCheckPolicies(long lbId) { + List healthCheckPolicies = new ArrayList(); + List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerId(lbId); + + for (LBHealthCheckPolicyVO policy : hcDbpolicies) { + String pingpath = policy.getpingpath(); + LbHealthCheckPolicy hDbPolicy = new LbHealthCheckPolicy(pingpath, policy.getDescription(), + policy.getResponseTime(), policy.getHealthcheckInterval(), policy.getHealthcheckThresshold(), + policy.getUnhealthThresshold(), policy.isRevoke()); + healthCheckPolicies.add(hDbPolicy); + } + return healthCheckPolicies; + } + @Override public List getExistingDestinations(long lbId) { List dstList = new ArrayList(); @@ -1323,7 +1686,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId()); dstIp = nic.getIp4Address(); - LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke()); + LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, + lbVmMap.isRevoke()); dstList.add(lbDst); } return dstList; @@ -1369,16 +1733,19 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements applyLoadBalancerConfig(lbRuleId); } catch (ResourceUnavailableException e) { if (isRollBackAllowedForProvider(lb)) { - /* NOTE : We use lb object to update db instead of lbBackup object since db layer will fail to update if there is no change in the object. + /* + * NOTE : We use lb object to update db instead of lbBackup + * object since db layer will fail to update if there is no + * change in the object. */ if (lbBackup.getName() != null) { - lb.setName(lbBackup.getName()); + lb.setName(lbBackup.getName()); } if (lbBackup.getDescription() != null) { lb.setDescription(lbBackup.getDescription()); } if (lbBackup.getAlgorithm() != null) { - lb.setAlgorithm(lbBackup.getAlgorithm()); + lb.setAlgorithm(lbBackup.getAlgorithm()); } lb.setState(lbBackup.getState()); _lbDao.update(lb.getId(), lb); @@ -1399,7 +1766,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } @Override - public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) throws PermissionDeniedException { + public List listLoadBalancerInstances(ListLoadBalancerRuleInstancesCmd cmd) + throws PermissionDeniedException { Account caller = UserContext.current().getCaller(); Long loadBalancerId = cmd.getId(); Boolean applied = cmd.isApplied(); @@ -1428,10 +1796,12 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } IPAddressVO addr = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()); - List userVms = _vmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), addr.getDataCenterId(), loadBalancer.getNetworkId()); + List userVms = _vmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), + addr.getDataCenterId(), loadBalancer.getNetworkId()); for (UserVmVO userVm : userVms) { - // if the VM is destroyed, being expunged, in an error state, or in an unknown state, skip it + // if the VM is destroyed, being expunged, in an error state, or in + // an unknown state, skip it switch (userVm.getState()) { case Destroyed: case Expunging: @@ -1449,10 +1819,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return loadBalancerInstances; } - @Override - public List getStickinessMethods(long networkid) - { + public List getStickinessMethods(long networkid) { String capability = getLBCapability(networkid, Capability.SupportedStickinessMethods.getName()); if (capability == null) { return null; @@ -1465,7 +1833,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } @Override - public List searchForLBStickinessPolicies(ListLBStickinessPoliciesCmd cmd) throws PermissionDeniedException { + public List searchForLBStickinessPolicies(ListLBStickinessPoliciesCmd cmd) + throws PermissionDeniedException { Account caller = UserContext.current().getCaller(); Long loadBalancerId = cmd.getLbRuleId(); LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); @@ -1480,6 +1849,20 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return sDbpolicies; } + @Override + public List searchForLBHealthCheckPolicies(ListLBHealthCheckPoliciesCmd cmd) + throws PermissionDeniedException { + Account caller = UserContext.current().getCaller(); + Long loadBalancerId = cmd.getLbRuleId(); + LoadBalancerVO loadBalancer = _lbDao.findById(loadBalancerId); + if (loadBalancer == null) { + return null; + } + _accountMgr.checkAccess(caller, null, true, loadBalancer); + List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerId(cmd.getLbRuleId()); + return hcDbpolicies; + } + @Override public Pair, Integer> searchForLoadBalancers(ListLoadBalancerRulesCmd cmd) { Long ipId = cmd.getPublicIpId(); @@ -1493,8 +1876,10 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements Account caller = UserContext.current().getCaller(); List permittedAccounts = new ArrayList(); - Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); - _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); + Ternary domainIdRecursiveListProject = new Ternary( + cmd.getDomainId(), cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, + domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); @@ -1510,13 +1895,15 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); lbVMSearch.and("instanceId", lbVMSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), JoinBuilder.JoinType.INNER); + sb.join("lbVMSearch", lbVMSearch, sb.entity().getId(), lbVMSearch.entity().getLoadBalancerId(), + JoinBuilder.JoinType.INNER); } if (zoneId != null) { SearchBuilder ipSearch = _ipAddressDao.createSearchBuilder(); ipSearch.and("zoneId", ipSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); - sb.join("ipSearch", ipSearch, sb.entity().getSourceIpAddressId(), ipSearch.entity().getId(), JoinBuilder.JoinType.INNER); + sb.join("ipSearch", ipSearch, sb.entity().getSourceIpAddressId(), ipSearch.entity().getId(), + JoinBuilder.JoinType.INNER); } if (tags != null && !tags.isEmpty()) { @@ -1528,7 +1915,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); sb.groupBy(sb.entity().getId()); - sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), + JoinBuilder.JoinType.INNER); } SearchCriteria sc = sb.create(); @@ -1561,7 +1949,6 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sc.setJoinParameters("ipSearch", "zoneId", zoneId); } - if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.LoadBalancer.toString()); @@ -1583,7 +1970,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements for (LoadBalancerVO lb : lbs) { List dstList = getExistingDestinations(lb.getId()); List policyList = this.getStickinessPolicies(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList); + List hcPolicyList = this.getHealthCheckPolicies(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); lbRules.add(loadBalancing); } return lbRules; @@ -1594,10 +1982,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements return _lbDao.findById(lbId); } - protected void removeLBRule(LoadBalancerVO rule) { - //remove the rule + protected void removeLBRule(LoadBalancerVO rule) { + // remove the rule _lbDao.remove(rule.getId()); } - - } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index ce65586ec6e..6742f7b378d 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -167,6 +167,7 @@ import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; +import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; import com.cloud.network.lb.LoadBalancingRule.LbStickinessPolicy; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.router.VirtualRouter.RedundantState; @@ -2382,11 +2383,12 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V for (LoadBalancerVO lb : lbs) { List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList); + List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId()); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); lbRules.add(loadBalancing); } } - + s_logger.debug("Found " + lbRules.size() + " load balancing rule(s) to apply as a part of domR " + router + " start."); if (!lbRules.isEmpty()) { createApplyLoadBalancingRulesCommands(lbRules, router, cmds, guestNetworkId); @@ -3284,7 +3286,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V for (LoadBalancerVO lb : lbs) { List dstList = _lbMgr.getExistingDestinations(lb.getId()); List policyList = _lbMgr.getStickinessPolicies(lb.getId()); - LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList,policyList); + List hcPolicyList = _lbMgr.getHealthCheckPolicies(lb.getId() ); + LoadBalancingRule loadBalancing = new LoadBalancingRule(lb, dstList, policyList, hcPolicyList); lbRules.add(loadBalancing); } return sendLBRules(router, lbRules, network.getId()); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index d70c45f1f8a..1f1f12edfc1 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -2103,10 +2103,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(QueryAsyncJobResultCmd.class); cmdList.add(AssignToLoadBalancerRuleCmd.class); cmdList.add(CreateLBStickinessPolicyCmd.class); + cmdList.add(CreateLBHealthCheckPolicyCmd .class); cmdList.add(CreateLoadBalancerRuleCmd.class); cmdList.add(DeleteLBStickinessPolicyCmd.class); + cmdList.add(DeleteLBHealthCheckPolicyCmd .class); cmdList.add(DeleteLoadBalancerRuleCmd.class); cmdList.add(ListLBStickinessPoliciesCmd.class); + cmdList.add(ListLBHealthCheckPoliciesCmd .class); cmdList.add(ListLoadBalancerRuleInstancesCmd.class); cmdList.add(ListLoadBalancerRulesCmd.class); cmdList.add(RemoveFromLoadBalancerRuleCmd.class); diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ca15bdaf781..4e39a71ef9d 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -27,6 +27,7 @@ UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE `h INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES ('VMware', '5.1', 128, 0, 32); DELETE FROM `cloud`.`configuration` where name='vmware.percluster.host.max'; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.nics.max', '7', 'Maximum allowed nics for Vms created on Xen'); +ALTER TABLE `cloud`.`load_balancer_vm_map` ADD state VARCHAR(40) NULL COMMENT 'service status updated by LB healthcheck manager'; alter table template_host_ref add state varchar(255); alter table template_host_ref add update_count bigint unsigned; @@ -97,6 +98,21 @@ CREATE TABLE `vpc_service_map` ( UNIQUE (`vpc_id`, `service`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`load_balancer_healthcheck_policies` ( + `id` bigint(20) NOT NULL auto_increment, + `uuid` varchar(40), + `load_balancer_id` bigint unsigned NOT NULL, + `pingpath` varchar(225) NULL DEFAULT '/', + `description` varchar(4096) NULL, + `response_time` int(11) DEFAULT 5, + `healthcheck_interval` int(11) DEFAULT 5, + `healthcheck_thresshold` int(11) DEFAULT 2, + `unhealth_thresshold` int(11) DEFAULT 10, + `revoke` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 is when rule is set for Revoke', + PRIMARY KEY (`id`), + UNIQUE KEY `id_UNIQUE` (`id`), + CONSTRAINT `fk_load_balancer_healthcheck_policies_loadbalancer_id` FOREIGN KEY(`load_balancer_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.instancename.flag', 'false', 'Append guest VM display Name (if set) to the internal name of the VM');