diff --git a/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigAnswer.java b/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigAnswer.java new file mode 100644 index 00000000000..e5167feded6 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigAnswer.java @@ -0,0 +1,27 @@ +// 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.Answer; + +public class GlobalLoadBalancerConfigAnswer extends Answer{ + + public GlobalLoadBalancerConfigAnswer(boolean success, String details) { + this.result = success; + this.details = details; + } +} diff --git a/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigCommand.java b/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigCommand.java new file mode 100644 index 00000000000..b3603c8be95 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/GlobalLoadBalancerConfigCommand.java @@ -0,0 +1,100 @@ +// 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.Command; + +import java.util.List; + +/** + * GlobalLoadBalancerConfigCommand used for sending the GSLB configuration to GSLB service provider + */ +public class GlobalLoadBalancerConfigCommand extends Command { + + // FQDN that represents the globally load balanced service + String domainName; + + // type of the globally load balanced service + String serviceType; + + // load balancing method to distribute traffic across the sites participating in global service load balancing + String lbMethod; + + // session persistence type + String persistenceType; + + // unique Id given per gslb rule, that is uniquely represents glsb rule on all participant sites + long gslbId; + + // true if global load balancer rule is being deleted + boolean revoked; + + // list of the site details that are participating in the GSLB service + List siteLoadBalancers; + + public GlobalLoadBalancerConfigCommand(String domainName, + String lbMethod, + String persistenceType, + String serviceType, + long gslbId, + boolean revoked) { + this.domainName = domainName; + this.serviceType = serviceType; + this.lbMethod = lbMethod; + this.persistenceType = persistenceType; + this.gslbId = gslbId; + this.revoked = revoked; + } + + public List getSiteDetails() { + return siteLoadBalancers; + } + + public void setSiteLoadBalancers(List siteLoadBalancers) { + this.siteLoadBalancers = siteLoadBalancers; + } + + public String getServiceType() { + return serviceType; + } + + public String getLoadBalancerMethod() { + return lbMethod; + } + + public String getPersistenceType() { + return persistenceType; + } + + public long getGslbId() { + return this.gslbId; + } + + public String getDomainName() { + return domainName; + } + + public boolean isForRevoke() { + return revoked; + } + + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/api/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java b/api/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java new file mode 100644 index 00000000000..cca5de83102 --- /dev/null +++ b/api/src/com/cloud/agent/api/routing/SiteLoadBalancerConfig.java @@ -0,0 +1,121 @@ +// 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; + +// details of site participating in the GLSB service, represents configuration load balancer rule and the zone +// in which the rule is configured +public class SiteLoadBalancerConfig { + + // true if the site details are local to the zone receiving 'GlobalLoadBalancerConfigCommand' + boolean local; + + // true if the site needs to be removed from GSLB service + boolean revoked; + + // service type of the 'site load balanced' service + String serviceType; + + // public IP corresponding to the site load balanced service + String servicePublicIp; + + // port corresponding to the site load balanced service + String servicePort; + + // Private IP corresponding to the GSLB service provider in the site. + String gslbProviderPrivateIp; + + // Public IP corresponding to the GSLB service provider in the site. + String gslbProviderPublicIp; + + // zone id in which site is located + long dataCenterId; + + public SiteLoadBalancerConfig(boolean revoked, String serviceType, String servicePublicIp, String servicePort, + long dataCenterId) { + this.revoked = revoked; + this.serviceType = serviceType; + this.servicePublicIp = servicePublicIp; + this.servicePort = servicePort; + this.dataCenterId = dataCenterId; + } + + public SiteLoadBalancerConfig(String gslbProviderPublicIP, String gslbProviderPrivateIp, boolean local, + boolean revoked, String serviceType, String servicePublicIp, String port, + long dataCenterId) { + this(revoked, serviceType, servicePublicIp, port, dataCenterId); + this.gslbProviderPrivateIp = gslbProviderPrivateIp; + this.gslbProviderPublicIp = gslbProviderPublicIP; + this.local = local; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public String getServicePublicIp() { + return servicePublicIp; + } + + public void SetServicePublicIp(String servicePublicIp) { + this.servicePublicIp = servicePublicIp; + } + + public String getServicePort() { + return servicePort; + } + + public void setServicePort(String port) { + this.servicePort = port; + } + + public String getGslbProviderPrivateIp() { + return gslbProviderPrivateIp; + } + + public void setGslbProviderPrivateIp(String privateIp) { + this.gslbProviderPrivateIp = privateIp; + } + + public String getGslbProviderPublicIp() { + return gslbProviderPublicIp; + } + + public long getDataCenterId() { + return dataCenterId; + } + + public void setGslbProviderPublicIp(String publicIp) { + this.gslbProviderPublicIp = publicIp; + } + + public boolean isLocal() { + return local; + } + + public void setLocal(boolean local) { + this.local = local; + } + + public boolean forRevoke() { + return revoked; + } +} \ No newline at end of file diff --git a/api/src/com/cloud/async/AsyncJob.java b/api/src/com/cloud/async/AsyncJob.java index 034c853e8f9..8e4aec0739a 100644 --- a/api/src/com/cloud/async/AsyncJob.java +++ b/api/src/com/cloud/async/AsyncJob.java @@ -16,11 +16,11 @@ // under the License. package com.cloud.async; -import java.util.Date; - import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import java.util.Date; + public interface AsyncJob extends Identity, InternalIdentity { public enum Type { None, @@ -48,7 +48,8 @@ public interface AsyncJob extends Identity, InternalIdentity { Condition, AutoScalePolicy, AutoScaleVmProfile, - AutoScaleVmGroup + AutoScaleVmGroup, + GlobalLoadBalancerRule } long getUserId(); diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index f38865c9e34..6fdd28cf165 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -114,6 +114,12 @@ public class EventTypes { public static final String EVENT_LB_HEALTHCHECKPOLICY_DELETE = "LB.HEALTHCHECKPOLICY.DELETE"; public static final String EVENT_LOAD_BALANCER_UPDATE = "LB.UPDATE"; + // Global Load Balancer rules + public static final String EVENT_ASSIGN_TO_GLOBAL_LOAD_BALANCER_RULE = "GLOBAL.LB.ASSIGN"; + public static final String EVENT_REMOVE_FROM_GLOBAL_LOAD_BALANCER_RULE = "GLOBAL.LB.REMOVE"; + public static final String EVENT_GLOBAL_LOAD_BALANCER_CREATE = "GLOBAL.LB.CREATE"; + public static final String EVENT_GLOBAL_LOAD_BALANCER_DELETE = "GLOBAL.LB.DELETE"; + // Account events public static final String EVENT_ACCOUNT_DISABLE = "ACCOUNT.DISABLE"; public static final String EVENT_ACCOUNT_CREATE = "ACCOUNT.CREATE"; diff --git a/api/src/com/cloud/region/ha/GlobalLoadBalancerRule.java b/api/src/com/cloud/region/ha/GlobalLoadBalancerRule.java new file mode 100644 index 00000000000..597304fa860 --- /dev/null +++ b/api/src/com/cloud/region/ha/GlobalLoadBalancerRule.java @@ -0,0 +1,89 @@ +// 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.region.ha; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +/** + * GlobalLoadBalancerRule defines a global (multi zone) load balancing configuration. + */ +public interface GlobalLoadBalancerRule extends Identity, InternalIdentity, ControlledEntity { + + enum Algorithm { + + RoundRobin, + LeastConn, + Proximity; + + public static boolean isValidAlgorithm(String algorithm) { + if (RoundRobin.name().equalsIgnoreCase(algorithm) || + LeastConn.name().equalsIgnoreCase(algorithm) || + Proximity.name().equalsIgnoreCase(algorithm)) { + return true; + } + return false; + } + } + enum Persistence { + + sourceip; + + public static boolean isValidPersistence(String persistence) { + if (sourceip.name().equalsIgnoreCase(persistence)) { + return true; + } + return false; + } + } + + enum ServiceType { + tcp, + udp; + public static boolean isValidServiceType(String serviceType) { + if (tcp.name().equalsIgnoreCase(serviceType) || udp.name().equalsIgnoreCase(serviceType)) { + return true; + } + return false; + } + } + enum State { + Staged, + Add, + Active, + Revoke + } + + public String getName(); + + public String getDescription(); + + public String getGslbDomain(); + + public String getAlgorithm(); + + public String getPersistence(); + + public int getRegion(); + + public long getAccountId(); + + public State getState(); + + public String getServiceType(); +} diff --git a/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java b/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java new file mode 100644 index 00000000000..e2f097e29a3 --- /dev/null +++ b/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java @@ -0,0 +1,47 @@ +// 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.region.ha; + +import org.apache.cloudstack.api.command.user.region.ha.gslb.*; + +import java.util.List; + +public interface GlobalLoadBalancingRulesService { + + /* + * methods for managing life cycle of global load balancing rules + */ + GlobalLoadBalancerRule createGlobalLoadBalancerRule(CreateGlobalLoadBalancerRuleCmd createGslbCmd); + + boolean deleteGlobalLoadBalancerRule(DeleteGlobalLoadBalancerRuleCmd deleteGslbCmd); + + GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalancerRuleCmd updateGslbCmd); + + /* + * methods for managing sites participating in global load balancing + */ + boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd assignToGslbCmd); + + boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRuleCmd removeFromGslbCmd); + + + GlobalLoadBalancerRule findById(long gslbRuleId); + + List listGlobalLoadBalancerRule(ListGlobalLoadBalancerRuleCmd listGslbCmd); + +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index f4c6c527d1a..c518830c92c 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -80,6 +80,10 @@ public class ApiConstants { public static final String IP6_GATEWAY = "ip6gateway"; public static final String GROUP = "group"; public static final String GROUP_ID = "groupid"; + public static final String GSLB_LB_METHOD = "gslblbmethod"; + public static final String GSLB_SERVICE_DOMAIN_NAME = "gslbdomainname"; + public static final String GSLB_SERVICE_TYPE = "gslbservicetype"; + public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; public static final String HA_ENABLE = "haenable"; public static final String HOST_ID = "hostid"; @@ -329,6 +333,7 @@ public class ApiConstants { public static final String LOAD_BALANCER_DEVICE_STATE = "lbdevicestate"; public static final String LOAD_BALANCER_DEVICE_CAPACITY = "lbdevicecapacity"; public static final String LOAD_BALANCER_DEVICE_DEDICATED = "lbdevicededicated"; + public static final String LOAD_BALANCER_RULE_LIST = "loadbalancerrulelist"; public static final String FIREWALL_DEVICE_ID = "fwdeviceid"; public static final String FIREWALL_DEVICE_NAME = "fwdevicename"; public static final String FIREWALL_DEVICE_STATE = "fwdevicestate"; @@ -445,6 +450,9 @@ public class ApiConstants { public static final String AUTOSCALE_USER_ID = "autoscaleuserid"; public static final String BAREMETAL_DISCOVER_NAME = "baremetaldiscovername"; public static final String UCS_DN = "ucsdn"; + public static final String GSLB_PROVIDER = "gslbprovider"; + public static final String GSLB_PROVIDER_PUBLIC_IP = "gslbproviderpublicip"; + public static final String GSLB_PROVIDER_PRIVATE_IP = "gslbproviderprivateip"; public static final String VM_SNAPSHOT_DESCRIPTION = "description"; public static final String VM_SNAPSHOT_DISPLAYNAME = "name"; public static final String VM_SNAPSHOT_ID = "vmsnapshotid"; diff --git a/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java b/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java index 97edb4c7c64..f3b3170445d 100644 --- a/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseAsyncCmd.java @@ -31,6 +31,7 @@ public abstract class BaseAsyncCmd extends BaseCmd { public static final String networkSyncObject = "network"; public static final String vpcSyncObject = "vpc"; public static final String snapshotHostSyncObject = "snapshothost"; + public static final String gslbSyncObject = "globalserverloadbalacner"; private AsyncJob job; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index 628a185e93d..d1e13023117 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -115,23 +115,9 @@ import com.cloud.domain.Domain; import com.cloud.event.Event; import com.cloud.host.Host; import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Service; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.Site2SiteCustomerGateway; -import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.Site2SiteVpnGateway; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.network.VpnUser; -import com.cloud.network.as.AutoScalePolicy; -import com.cloud.network.as.AutoScaleVmGroup; -import com.cloud.network.as.AutoScaleVmProfile; -import com.cloud.network.as.Condition; -import com.cloud.network.as.Counter; +import com.cloud.network.as.*; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.HealthCheckPolicy; @@ -152,13 +138,9 @@ import com.cloud.org.Cluster; import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectInvitation; +import com.cloud.region.ha.GlobalLoadBalancerRule; import com.cloud.server.ResourceTag; -import com.cloud.storage.GuestOS; -import com.cloud.storage.S3; -import com.cloud.storage.Snapshot; -import com.cloud.storage.StoragePool; -import com.cloud.storage.Swift; -import com.cloud.storage.Volume; +import com.cloud.storage.*; import com.cloud.storage.snapshot.SnapshotPolicy; import com.cloud.storage.snapshot.SnapshotSchedule; import com.cloud.template.VirtualMachineTemplate; @@ -169,8 +151,17 @@ import com.cloud.uservm.UserVm; import com.cloud.vm.InstanceGroup; import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.snapshot.VMSnapshot; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; +import org.apache.cloudstack.api.response.*; +import org.apache.cloudstack.region.Region; + +import java.text.DecimalFormat; +import java.util.EnumSet; +import java.util.List; public interface ResponseGenerator { UserResponse createUserResponse(UserAccount user); @@ -209,6 +200,8 @@ public interface ResponseGenerator { IPAddressResponse createIPAddressResponse(IpAddress ipAddress); + GlobalLoadBalancerResponse createGlobalLoadBalancerResponse(GlobalLoadBalancerRule globalLoadBalancerRule); + LoadBalancerResponse createLoadBalancerResponse(LoadBalancer loadBalancer); LBStickinessResponse createLBStickinessPolicyResponse(List stickinessPolicies, LoadBalancer lb); diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..1c07a0aad53 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/AssignToGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,128 @@ +// 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.region.ha.gslb; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.utils.StringUtils; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = "assignToGlobalLoadBalancerRule", description="Assign load balancer rule or list of load " + + "balancer rules to a global load balancer rules.", responseObject=SuccessResponse.class) +public class AssignToGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger.getLogger(AssignToGlobalLoadBalancerRuleCmd.class.getName()); + + private static final String s_name = "assigntogloballoadbalancerruleresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, + required=true, description="the ID of the global load balancer rule") + private Long id; + + @Parameter(name=ApiConstants.LOAD_BALANCER_RULE_LIST, type=CommandType.LIST, collectionType=CommandType.UUID, + entityType = FirewallRuleResponse.class, required=true, description="the list load balancer rules that " + + "will be assigned to gloabal load balacner rule") + private List loadBalancerRulesIds; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getGlobalLoadBalancerRuleId() { + return id; + } + + public List getLoadBalancerRulesIds() { + return loadBalancerRulesIds; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Inject + public GlobalLoadBalancingRulesService _gslbService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + GlobalLoadBalancerRule globalLoadBalancerRule = _entityMgr.findById(GlobalLoadBalancerRule.class, + getGlobalLoadBalancerRuleId()); + if (globalLoadBalancerRule == null) { + return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked + } + return globalLoadBalancerRule.getAccountId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_ASSIGN_TO_GLOBAL_LOAD_BALANCER_RULE; + } + + @Override + public String getEventDescription() { + return "applying load balancer rules " + StringUtils.join(getLoadBalancerRulesIds(), ",") + + " to global load balancer rule " + getGlobalLoadBalancerRuleId(); + } + + @Override + public void execute(){ + UserContext.current().setEventDetails("Global Load balancer rule Id: "+ getGlobalLoadBalancerRuleId()+ " VmIds: " + + StringUtils.join(getLoadBalancerRulesIds(), ",")); + boolean result = _gslbService.assignToGlobalLoadBalancerRule(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign global load balancer rule"); + } + } + + @Override + public String getSyncObjType() { + return BaseAsyncCmd.gslbSyncObject; + } + + @Override + public Long getSyncObjId() { + GlobalLoadBalancerRule gslb = _gslbService.findById(id); + if(gslb == null){ + throw new InvalidParameterValueException("Unable to find load balancer rule: " + id); + } + return gslb.getId(); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..cd559d8c470 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,179 @@ +// 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.region.ha.gslb; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +@APICommand(name = "createGlobalLoadBalancerRule", description="Creates a global load balancer rule", + responseObject=GlobalLoadBalancerResponse.class) +public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { + + public static final Logger s_logger = Logger.getLogger(CreateGlobalLoadBalancerRuleCmd.class.getName()); + + private static final String s_name = "creategloballoadbalancerruleresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="name of the load balancer rule") + private String globalLoadBalancerRuleName; + + @Parameter(name=ApiConstants.DESCRIPTION, type=CommandType.STRING, description="the description of the load balancer rule", length=4096) + private String description; + + @Parameter(name=ApiConstants.REGION_ID, type=CommandType.INTEGER, entityType = RegionResponse.class, required=true, description="region where the global load balancer is going to be created.") + private Integer regionId; + + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="the account associated with the global load balancer. Must be used with the domainId parameter.") + private String accountName; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class, description="the domain ID associated with the load balancer") + private Long domainId; + + @Parameter(name=ApiConstants.GSLB_LB_METHOD, type=CommandType.STRING, required=false, description="load balancer algorithm (roundrobin, leastconn, proximity) " + + "that method is used to distribute traffic across the zones participating in global server load balancing, if not specified defaults to 'round robin'") + private String algorithm; + + @Parameter(name=ApiConstants.GSLB_STICKY_SESSION_METHOD, type=CommandType.STRING, required=false, description="session sticky method (sourceip) if not specified defaults to sourceip") + private String stickyMethod; + + @Parameter(name=ApiConstants.GSLB_SERVICE_DOMAIN_NAME, type = CommandType.STRING, required = true, description = "domain name for the GSLB service.") + private String serviceDomainName; + + @Parameter(name=ApiConstants.GSLB_SERVICE_TYPE, type = CommandType.STRING, required = true, description = "GSLB service type (tcp, udp)") + private String serviceType; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getName() { + return globalLoadBalancerRuleName; + } + + public String getDescription() { + return description; + } + + public String getAlgorithm() { + return algorithm; + } + + public String getGslbMethod() { + return algorithm; + } + + public String getStickyMethod() { + return stickyMethod; + } + + public String getServiceDomainName() { + return serviceDomainName; + } + + public Integer getRegionId() { + return regionId; + } + + public String getServiceType() { + return serviceType; + } + + @Inject + private GlobalLoadBalancingRulesService _gslbService; + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() throws ResourceAllocationException, ResourceUnavailableException { + + UserContext callerContext = UserContext.current(); + GlobalLoadBalancerRule rule = _entityMgr.findById(GlobalLoadBalancerRule.class, getEntityId()); + GlobalLoadBalancerResponse response = null; + if (rule != null) { + response = _responseGenerator.createGlobalLoadBalancerResponse(rule); + setResponseObject(response); + } + response.setResponseName(getCommandName()); + } + + @Override + public void create() { + try { + GlobalLoadBalancerRule gslbRule = _gslbService.createGlobalLoadBalancerRule(this); + this.setEntityId(gslbRule.getId()); + this.setEntityUuid(gslbRule.getUuid()); + UserContext.current().setEventDetails("Rule Id: " + getEntityId()); + } catch (Exception ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage()); + }finally { + + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_GLOBAL_LOAD_BALANCER_CREATE; + } + + @Override + public String getEventDescription() { + return "creating a global load balancer: " + getName() + " for account: " + getAccountName(); + + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.GlobalLoadBalancerRule; + } + + @Override + public long getEntityOwnerId() { + Long accountId = finalyzeAccountId(accountName, domainId, null, true); + if (accountId == null) { + return UserContext.current().getCaller().getId(); + } + return accountId; + } + + public String getAccountName() { + return accountName; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..424b1072887 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,108 @@ +// 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.region.ha.gslb; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +@APICommand(name = "deleteGlobalLoadBalancerRule", description="Deletes a global load balancer rule.", responseObject=SuccessResponse.class) +public class DeleteGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { + + public static final Logger s_logger = Logger.getLogger(DeleteGlobalLoadBalancerRuleCmd.class.getName()); + + private static final String s_name = "deletegloballoadbalancerruleresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, required=true, description="the ID of the global load balancer rule") + private Long id; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getGlobalLoadBalancerId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Inject + public GlobalLoadBalancingRulesService _gslbService; + + @Override + public long getEntityOwnerId() { + GlobalLoadBalancerRule lb = _entityMgr.findById(GlobalLoadBalancerRule.class, getGlobalLoadBalancerId()); + if (lb != null) { + return lb.getAccountId(); + } + + 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_LOAD_BALANCER_DELETE; + } + + @Override + public String getEventDescription() { + return "deleting global load balancer: " + getGlobalLoadBalancerId(); + } + + @Override + public void execute(){ + _gslbService.deleteGlobalLoadBalancerRule(this); + UserContext.current().setEventDetails("Deleting global Load balancer Id: " + getGlobalLoadBalancerId()); + } + + @Override + public String getSyncObjType() { + return BaseAsyncCmd.networkSyncObject; + } + + @Override + public Long getSyncObjId() { + return null; + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.GlobalLoadBalancerRule; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..dae861a35b1 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,92 @@ +// 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.region.ha.gslb; + +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; + +@APICommand(name = "listGlobalLoadBalancerRules", description = "Lists load balancer rules.", responseObject = GlobalLoadBalancerResponse.class) +public class ListGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd { + public static final Logger s_logger = Logger.getLogger(ListGlobalLoadBalancerRuleCmd.class.getName()); + + private static final String s_name = "listgloballoadbalancerrulesresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, description = "the ID of the global load balancer rule") + private Long id; + + @Parameter(name = ApiConstants.REGION_ID, type = CommandType.UUID, entityType = RegionResponse.class, description = "region ID") + private Integer regionId; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public Integer getRegionId() { + return regionId; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Inject + public GlobalLoadBalancingRulesService _gslbService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() { + List globalLoadBalancers = _gslbService.listGlobalLoadBalancerRule(this); + ListResponse gslbRuleResponse = new ListResponse(); + List gslbResponses = new ArrayList(); + if (globalLoadBalancers != null) { + for (GlobalLoadBalancerRule gslbRule: globalLoadBalancers) { + GlobalLoadBalancerResponse gslbResponse = _responseGenerator.createGlobalLoadBalancerResponse(gslbRule); + gslbResponse.setObjectName("globalloadbalancerrule"); + gslbResponses.add(gslbResponse); + } + } + gslbRuleResponse.setResponses(gslbResponses); + gslbRuleResponse.setResponseName(getCommandName()); + this.setResponseObject(gslbRuleResponse); + } + +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..fa051af54cb --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/RemoveFromGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,125 @@ +// 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.region.ha.gslb; + +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.utils.StringUtils; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import java.util.List; + +@APICommand(name = "removeFromGlobalLoadBalancerRule", description="Removes a load balancer rule association with" + + " global load balancer rule", responseObject=SuccessResponse.class) +public class RemoveFromGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(RemoveFromGlobalLoadBalancerRuleCmd.class.getName()); + + private static final String s_name = "removefromloadbalancerruleresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, + required=true, description="The ID of the load balancer rule") + private Long id; + + @Parameter(name=ApiConstants.LOAD_BALANCER_RULE_LIST, type=CommandType.LIST, collectionType=CommandType.UUID, + entityType = FirewallRuleResponse.class, required=true, description="the list load balancer rules that " + + "will be assigned to gloabal load balacner rule") + private List loadBalancerRulesIds; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getGlobalLoadBalancerRuleId() { + return id; + } + + public List getLoadBalancerRulesIds() { + return loadBalancerRulesIds; + } + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Inject + public GlobalLoadBalancingRulesService _gslbService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + GlobalLoadBalancerRule globalLoadBalancerRule = _entityMgr.findById(GlobalLoadBalancerRule.class, getGlobalLoadBalancerRuleId()); + if (globalLoadBalancerRule == null) { + return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked + } + return globalLoadBalancerRule.getAccountId(); + } + + @Override + public String getEventType() { + return EventTypes.EVENT_REMOVE_FROM_GLOBAL_LOAD_BALANCER_RULE; + } + + @Override + public String getEventDescription() { + return "removing load balancer rules:" + StringUtils.join(getLoadBalancerRulesIds(), ",") + + " from global load balancer: " + getGlobalLoadBalancerRuleId(); + } + + @Override + public void execute(){ + UserContext.current().setEventDetails("Global Load balancer rule Id: "+ getGlobalLoadBalancerRuleId()+ " VmIds: " + + StringUtils.join(getLoadBalancerRulesIds(), ",")); + boolean result = _gslbService.removeFromGlobalLoadBalancerRule(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove load balancer rule from global load balancer rule"); + } + } + + @Override + public String getSyncObjType() { + return BaseAsyncCmd.gslbSyncObject; + } + + @Override + public Long getSyncObjId() { + GlobalLoadBalancerRule gslb = _gslbService.findById(id); + if(gslb == null){ + throw new InvalidParameterValueException("Unable to find load balancer rule: " + id); + } + return gslb.getId(); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java new file mode 100644 index 00000000000..10694e1633e --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/UpdateGlobalLoadBalancerRuleCmd.java @@ -0,0 +1,96 @@ +// 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.region.ha.gslb; + +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.LoadBalancerResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +@APICommand(name = "updateGlobalLoadBalancerRule", description = "update global load balancer rules.", responseObject = LoadBalancerResponse.class) +public class UpdateGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd { + public static final Logger s_logger = Logger.getLogger(GlobalLoadBalancerResponse.class.getName()); + + private static final String s_name = "updategloballoadbalancerruleresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, + required=true, description="the ID of the global load balancer rule") + private Long id; + + @Parameter(name=ApiConstants.DESCRIPTION, type=CommandType.STRING, description="the description of the load balancer rule", length=4096) + private String description; + + @Parameter(name=ApiConstants.GSLB_LB_METHOD, type=CommandType.STRING, required=false, description="load balancer algorithm (roundrobin, leastconn, proximity) " + + "that is used to distributed traffic across the zones participating in global server load balancing, if not specified defaults to 'round robin'") + private String algorithm; + + @Parameter(name=ApiConstants.GSLB_STICKY_SESSION_METHOD, type=CommandType.STRING, required=false, description="session sticky method (sourceip) if not specified defaults to sourceip") + private String stickyMethod; + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getDescription() { + return description; + } + + public String getAlgorithm() { + return algorithm; + } + + public String getGslbMethod() { + return algorithm; + } + + public String getStickyMethod() { + return stickyMethod; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Inject + public GlobalLoadBalancingRulesService _gslbService; + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() { + _gslbService.updateGlobalLoadBalancerRule(this); + } + +} diff --git a/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java new file mode 100644 index 00000000000..0fd064f41b5 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java @@ -0,0 +1,125 @@ +// 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.region.ha.GlobalLoadBalancerRule; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +@EntityReference(value= GlobalLoadBalancerRule.class) +public class GlobalLoadBalancerResponse extends BaseResponse implements ControlledEntityResponse { + + @SerializedName(ApiConstants.ID) + @Param(description = "global load balancer rule ID") + private String id; + + @SerializedName(ApiConstants.NAME) + @Param(description = "name of the global load balancer rule") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) + @Param(description = "the description of the global load balancer rule") + private String description; + + @SerializedName(ApiConstants.GSLB_SERVICE_DOMAIN_NAME) + @Param(description = "DNS domain name given for the global load balancer") + private String gslbDomainName; + + @SerializedName(ApiConstants.GSLB_LB_METHOD) + @Param(description = "Load balancing method used for the global load balancer") + private String algorithm; + + @SerializedName(ApiConstants.GSLB_STICKY_SESSION_METHOD) + @Param(description = "session persistence method used for the global load balancer") + private String stickyMethod; + + @SerializedName(ApiConstants.REGION_ID) + @Param(description = "Region Id in which global load balancer is created") + private Integer regionId; + + @SerializedName(ApiConstants.ACCOUNT) + @Param(description = "the account of the load balancer rule") + private String accountName; + + @SerializedName(ApiConstants.PROJECT_ID) @Param(description="the project id of the load balancer") + private String projectId; + + @SerializedName(ApiConstants.PROJECT) @Param(description="the project name of the load balancer") + private String projectName; + + @SerializedName(ApiConstants.DOMAIN_ID) + @Param(description = "the domain ID of the load balancer rule") + private String domainId; + + @SerializedName(ApiConstants.DOMAIN) + @Param(description = "the domain of the load balancer rule") + private String domainName; + + public void setRegionIdId(Integer regionId) { + this.regionId = regionId; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public void setStickyMethod(String stickyMethod) { + this.stickyMethod = stickyMethod; + } + + public void setServiceDomainName(String domainName) { + this.gslbDomainName = domainName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + @Override + public void setProjectId(String projectId) { + this.projectId = projectId; + } + + @Override + public void setProjectName(String projectName) { + this.projectName = projectName; + } + + @Override + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } +} diff --git a/api/src/org/apache/cloudstack/region/Region.java b/api/src/org/apache/cloudstack/region/Region.java index f8926ee8d07..7119f1b2c14 100644 --- a/api/src/org/apache/cloudstack/region/Region.java +++ b/api/src/org/apache/cloudstack/region/Region.java @@ -16,6 +16,9 @@ // under the License. package org.apache.cloudstack.region; +import java.util.ArrayList; +import java.util.List; + /** * */ @@ -29,4 +32,50 @@ public interface Region { public String getEndPoint(); + + public boolean checkIfServiceEnabled(Service service); + + /** + * A region level service, is a service that constitute services across one or more zones in the region or a service + * made available to all the zones in the region. + */ + public static class Service { + + private String name; + private static List regionServices = new ArrayList(); + + public static final Service Gslb = new Service("Gslb"); + + public Service(String name ) { + this.name = name; + regionServices.add(this); + } + + public String getName() { + return name; + } + + } + + /** + * A provider provides the region level service in a zone. + */ + public static class Provider { + + private static List supportedProviders = new ArrayList(); + private String name; + private Service service; + + public static final Provider Netscaler = new Provider("Netscaler", Service.Gslb); + + public Provider(String name, Service service) { + this.name = name; + this.service = service; + supportedProviders.add(this); + } + + public String getName() { + return name; + } + } } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 492f7f909f6..3b3ffdfae09 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -551,6 +551,14 @@ updateRegion=1 removeRegion=1 listRegions=15 +#### GSLB (Global Server Load Balancing) commands +createGlobalLoadBalancerRule=15 +deleteGlobalLoadBalancerRule=15 +updateGlobalLoadBalancerRule=15 +listGlobalLoadBalancerRules=15 +assignToGlobalLoadBalancerRule=15 +removeFromGlobalLoadBalancerRule=15 + ### VM Snapshot commands listVMSnapshot=15 createVMSnapshot=15 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 3e75c3f1afe..77f6b60bfe8 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 @@ -31,14 +31,7 @@ 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; -import com.cloud.api.commands.ConfigureF5LoadBalancerCmd; -import com.cloud.api.commands.DeleteExternalLoadBalancerCmd; -import com.cloud.api.commands.DeleteF5LoadBalancerCmd; -import com.cloud.api.commands.ListExternalLoadBalancersCmd; -import com.cloud.api.commands.ListF5LoadBalancerNetworksCmd; -import com.cloud.api.commands.ListF5LoadBalancersCmd; +import com.cloud.api.commands.*; import com.cloud.api.response.F5LoadBalancerResponse; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -47,35 +40,17 @@ import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; -import com.cloud.network.ExternalLoadBalancerDeviceManager; -import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkModel; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PublicIpAddress; -import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; -import com.cloud.network.dao.ExternalLoadBalancerDeviceVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkExternalLoadBalancerDao; -import com.cloud.network.dao.NetworkExternalLoadBalancerVO; -import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.dao.*; import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.resource.F5BigIpResource; @@ -89,6 +64,13 @@ import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.google.gson.Gson; +import org.apache.cloudstack.api.response.ExternalLoadBalancerResponse; +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.*; @Local(value = {NetworkElement.class, LoadBalancingServiceProvider.class, IpDeployer.class}) public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, IpDeployer, F5ExternalLoadBalancerElementService, ExternalLoadBalancerDeviceManager { @@ -295,7 +277,8 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan pNetwork = physicalNetworks.get(0); String deviceType = NetworkDevice.F5BigIpLoadBalancer.getName(); - lbDeviceVO = addExternalLoadBalancer(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceType, new F5BigIpResource()); + lbDeviceVO = addExternalLoadBalancer(pNetwork.getId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), + deviceType, new F5BigIpResource(), false, null, null); if (lbDeviceVO != null) { lbHost = _hostDao.findById(lbDeviceVO.getHostId()); @@ -348,7 +331,8 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan throw new InvalidParameterValueException("Invalid F5 load balancer device type"); } - return addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, new F5BigIpResource()); + return addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), + deviceName, new F5BigIpResource(), false, null, null); } diff --git a/plugins/network-elements/netscaler/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java b/plugins/network-elements/netscaler/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java index 80c8cb94ea7..e4327b4348c 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java +++ b/plugins/network-elements/netscaler/src/com/cloud/api/commands/AddNetscalerLoadBalancerCmd.java @@ -15,23 +15,18 @@ package com.cloud.api.commands; -import javax.inject.Inject; - -import org.apache.cloudstack.api.*; -import org.apache.cloudstack.api.response.PhysicalNetworkResponse; -import org.apache.log4j.Logger; -import org.apache.cloudstack.api.APICommand; import com.cloud.api.response.NetscalerLoadBalancerResponse; import com.cloud.event.EventTypes; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.network.dao.ExternalLoadBalancerDeviceVO; import com.cloud.network.element.NetscalerLoadBalancerElementService; import com.cloud.user.UserContext; import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import javax.inject.Inject; @APICommand(name = "addNetscalerLoadBalancer", responseObject=NetscalerLoadBalancerResponse.class, description="Adds a netscaler load balancer device") public class AddNetscalerLoadBalancerCmd extends BaseAsyncCmd { @@ -60,6 +55,18 @@ public class AddNetscalerLoadBalancerCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.NETWORK_DEVICE_TYPE, type = CommandType.STRING, required = true, description = "Netscaler device type supports NetscalerMPXLoadBalancer, NetscalerVPXLoadBalancer, NetscalerSDXLoadBalancer") private String deviceType; + @Parameter(name = ApiConstants.GSLB_PROVIDER, type = CommandType.BOOLEAN, required = false, + description = "true if NetScaler device being added is for providing GSLB service") + private boolean isGslbProvider; + + @Parameter(name = ApiConstants.GSLB_PROVIDER_PUBLIC_IP, type = CommandType.STRING, required = false, + description = "public IP of the site") + private String gslbSitePublicIp; + + @Parameter(name = ApiConstants.GSLB_PROVIDER_PRIVATE_IP, type = CommandType.STRING, required = false, + description = "public IP of the site") + private String gslbSitePrivateIp; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -84,6 +91,18 @@ public class AddNetscalerLoadBalancerCmd extends BaseAsyncCmd { return deviceType; } + public boolean isGslbProvider() { + return isGslbProvider; + } + + public String getSitePublicIp() { + return gslbSitePublicIp; + } + + public String getSitePrivateIp() { + return gslbSitePrivateIp; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// 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 a90440cc2f3..17bb7cc1b6a 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 @@ -16,35 +16,16 @@ // under the License. package com.cloud.network.element; -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.inject.Inject; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; import com.cloud.agent.api.routing.SetStaticNatRulesCommand; import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.api.ApiDBUtils; -import com.cloud.api.commands.AddNetscalerLoadBalancerCmd; -import com.cloud.api.commands.ConfigureNetscalerLoadBalancerCmd; -import com.cloud.api.commands.DeleteNetscalerLoadBalancerCmd; -import com.cloud.api.commands.ListNetscalerLoadBalancerNetworksCmd; -import com.cloud.api.commands.ListNetscalerLoadBalancersCmd; +import com.cloud.api.commands.*; import com.cloud.api.response.NetscalerLoadBalancerResponse; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -56,40 +37,19 @@ import com.cloud.dc.HostPodVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterIpAddressDao; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; -import com.cloud.network.ExternalLoadBalancerDeviceManager; -import com.cloud.network.ExternalLoadBalancerDeviceManagerImpl; -import com.cloud.network.IpAddress; -import com.cloud.network.NetScalerPodVO; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkModel; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PublicIpAddress; import com.cloud.network.as.AutoScaleCounter; import com.cloud.network.as.AutoScaleCounter.AutoScaleCounterType; -import com.cloud.network.dao.ExternalLoadBalancerDeviceDao; -import com.cloud.network.dao.ExternalLoadBalancerDeviceVO; -import com.cloud.network.dao.NetScalerPodDao; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkExternalLoadBalancerDao; -import com.cloud.network.dao.NetworkExternalLoadBalancerVO; -import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.dao.*; import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; @@ -110,10 +70,20 @@ import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; import com.google.gson.Gson; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import org.apache.cloudstack.region.gslb.GslbServiceProvider; +import org.apache.log4j.Logger; -@Local(value = {NetworkElement.class, StaticNatServiceProvider.class, LoadBalancingServiceProvider.class}) -public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager, IpDeployer, -StaticNatServiceProvider { +import javax.ejb.Local; +import javax.inject.Inject; +import java.net.URI; +import java.util.*; + +@Local(value = {NetworkElement.class, StaticNatServiceProvider.class, LoadBalancingServiceProvider.class, GslbServiceProvider.class}) +public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl implements LoadBalancingServiceProvider, + NetscalerLoadBalancerElementService, ExternalLoadBalancerDeviceManager, IpDeployer, StaticNatServiceProvider, + GslbServiceProvider { private static final Logger s_logger = Logger.getLogger(NetscalerElement.class); public static final AutoScaleCounterType AutoScaleCounterSnmp = new AutoScaleCounterType("snmp"); @@ -149,6 +119,8 @@ StaticNatServiceProvider { NetScalerPodDao _netscalerPodDao; @Inject DataCenterIpAddressDao _privateIpAddressDao; + @Inject + ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao; private boolean canHandle(Network config, Service service) { DataCenter zone = _dcDao.findById(config.getDataCenterId()); @@ -336,7 +308,26 @@ StaticNatServiceProvider { throw new InvalidParameterValueException(msg); } - ExternalLoadBalancerDeviceVO lbDeviceVO = addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, new NetscalerResource()); + if (cmd.isGslbProvider()) { + + if (!deviceName.equals(NetworkDevice.NetscalerVPXLoadBalancer.getName()) && + !deviceName.equals(NetworkDevice.NetscalerMPXLoadBalancer.getName())) { + String msg = "Only Netscaler VPX or MPX load balancers can be specified as GSLB service provider"; + s_logger.debug(msg); + throw new InvalidParameterValueException(msg); + } + + if (cmd.getSitePublicIp() == null || cmd.getSitePrivateIp() == null) { + String msg = "Public and Privae IP needs to provided for NetScaler that will be GSLB provider"; + s_logger.debug(msg); + throw new InvalidParameterValueException(msg); + } + } + + ExternalLoadBalancerDeviceVO lbDeviceVO = addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), + cmd.getUsername(), cmd.getPassword(), deviceName, new NetscalerResource(), cmd.isGslbProvider(), + cmd.getSitePublicIp(), cmd.getSitePrivateIp()); + return lbDeviceVO; } @@ -816,7 +807,6 @@ StaticNatServiceProvider { return null; } - @Override public List updateHealthChecks(Network network, List lbrules) { if (canHandle(network, Service.Lb)) { @@ -831,10 +821,73 @@ StaticNatServiceProvider { return null; } - @Override public List getLBHealthChecks(Network network, List rules) throws ResourceUnavailableException { return super.getLBHealthChecks(network, rules); + } + @Override + public boolean applyGlobalLoadBalancerRule(long zoneId, GlobalLoadBalancerConfigCommand gslbConfigCmd) + throws ResourceUnavailableException { + + long zoneGslbProviderHosId = 0; + + // find the NetScaler device configured as gslb service provider in the zone + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + if (nsGslbProvider == null) { + String msg = "Unable to find a NetScaler configured as gslb service provider in zone " + zoneId; + s_logger.debug(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); + } + + // get the host Id corresponding to NetScaler acting as GSLB service provider in the zone + zoneGslbProviderHosId = nsGslbProvider.getHostId(); + + // send gslb configuration to NetScaler device + Answer answer = _agentMgr.easySend(zoneGslbProviderHosId, gslbConfigCmd); + if (answer == null || !answer.getResult()) { + String msg = "Unable to apply global load balancer rule to the gslb service provider in zone " + zoneId; + s_logger.debug(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, zoneId); + } + + return true; + } + + private ExternalLoadBalancerDeviceVO findGslbProvider(long zoneId) { + List pNtwks = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, TrafficType.Guest); + if (pNtwks.isEmpty() || pNtwks.size() > 1) { + throw new InvalidParameterValueException("Unable to get physical network in zone id = " + zoneId); + } + PhysicalNetworkVO physNetwork = pNtwks.get(0); + ExternalLoadBalancerDeviceVO nsGslbProvider = _externalLoadBalancerDeviceDao.findGslbServiceProvider( + physNetwork.getId(), Provider.Netscaler.getName()); + return nsGslbProvider; + } + + @Override + public boolean isServiceEnabledInZone(long zoneId) { + + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + //return true if a NetScaler device is configured in the zone + return (nsGslbProvider != null); + } + + @Override + public String getZoneGslbProviderPublicIp(long zoneId) { + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + if (nsGslbProvider != null) { + return nsGslbProvider.getGslbSitePublicIP(); + } + return null; + } + + @Override + public String getZoneGslbProviderPrivateIp(long zoneId) { + ExternalLoadBalancerDeviceVO nsGslbProvider = findGslbProvider(zoneId); + if (nsGslbProvider != null) { + return nsGslbProvider.getGslbSitePrivateIP(); + } + return null; } } 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 c09869b996a..b82176b7e37 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 @@ -16,17 +16,6 @@ // under the License. package com.cloud.network.resource; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - import com.citrix.netscaler.nitro.exception.nitro_exception; import com.citrix.netscaler.nitro.resource.base.base_response; import com.citrix.netscaler.nitro.resource.config.autoscale.autoscalepolicy; @@ -35,23 +24,10 @@ 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; -import com.citrix.netscaler.nitro.resource.config.lb.lbmetrictable_metric_binding; -import com.citrix.netscaler.nitro.resource.config.lb.lbmonitor; -import com.citrix.netscaler.nitro.resource.config.lb.lbmonitor_metric_binding; -import com.citrix.netscaler.nitro.resource.config.lb.lbvserver; -import com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding; -import com.citrix.netscaler.nitro.resource.config.lb.lbvserver_servicegroup_binding; -import com.citrix.netscaler.nitro.resource.config.network.Interface; -import com.citrix.netscaler.nitro.resource.config.network.inat; -import com.citrix.netscaler.nitro.resource.config.network.vlan; -import com.citrix.netscaler.nitro.resource.config.network.vlan_interface_binding; -import com.citrix.netscaler.nitro.resource.config.network.vlan_nsip_binding; -import com.citrix.netscaler.nitro.resource.config.ns.nsconfig; -import com.citrix.netscaler.nitro.resource.config.ns.nshardware; -import com.citrix.netscaler.nitro.resource.config.ns.nsip; -import com.citrix.netscaler.nitro.resource.config.ns.nstimer; -import com.citrix.netscaler.nitro.resource.config.ns.nstimer_autoscalepolicy_binding; +import com.citrix.netscaler.nitro.resource.config.gslb.*; +import com.citrix.netscaler.nitro.resource.config.lb.*; +import com.citrix.netscaler.nitro.resource.config.network.*; +import com.citrix.netscaler.nitro.resource.config.ns.*; import com.citrix.netscaler.nitro.resource.stat.lb.lbvserver_stats; import com.citrix.netscaler.nitro.service.nitro_service; import com.citrix.netscaler.nitro.util.filtervalue; @@ -60,38 +36,12 @@ import com.citrix.sdx.nitro.resource.config.mps; import com.citrix.sdx.nitro.resource.config.ns; import com.citrix.sdx.nitro.resource.config.xen_vpx_image; import com.cloud.agent.IAgentControl; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; -import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; -import com.cloud.agent.api.MaintainAnswer; -import com.cloud.agent.api.MaintainCommand; -import com.cloud.agent.api.PingCommand; -import com.cloud.agent.api.ReadyAnswer; -import com.cloud.agent.api.ReadyCommand; -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; -import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; -import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.*; +import com.cloud.agent.api.routing.*; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.LoadBalancerTO; -import com.cloud.agent.api.to.LoadBalancerTO.AutoScalePolicyTO; -import com.cloud.agent.api.to.LoadBalancerTO.AutoScaleVmGroupTO; -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.LoadBalancerTO.*; import com.cloud.agent.api.to.StaticNatRuleTO; -import org.apache.cloudstack.api.ApiConstants; import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.network.rules.LbStickinessMethod.StickinessMethodType; @@ -102,6 +52,11 @@ import com.cloud.utils.Pair; import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.net.NetUtils; import com.google.gson.Gson; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.log4j.Logger; + +import javax.naming.ConfigurationException; +import java.util.*; class NitroError { static final int NS_RESOURCE_EXISTS = 273; @@ -109,6 +64,7 @@ class NitroError { static final int NS_NO_SERIVCE = 344; static final int NS_OPERATION_NOT_PERMITTED = 257; static final int NS_INTERFACE_ALREADY_BOUND_TO_VLAN = 2080; + static final int NS_GSLB_DOMAIN_ALREADY_BOUND = 1842; } public class NetscalerResource implements ServerResource { @@ -401,9 +357,11 @@ public class NetscalerResource implements ServerResource { return execute((DestroyLoadBalancerApplianceCommand) cmd, numRetries); } else if (cmd instanceof SetStaticNatRulesCommand) { return execute((SetStaticNatRulesCommand) cmd, numRetries); + } else if (cmd instanceof GlobalLoadBalancerConfigCommand) { + return execute((GlobalLoadBalancerConfigCommand) cmd, numRetries); } else if (cmd instanceof HealthCheckLBConfigCommand) { return execute((HealthCheckLBConfigCommand) cmd, numRetries); - }else { + } else { return Answer.createUnsupportedCommandAnswer(cmd); } } @@ -896,6 +854,592 @@ public class NetscalerResource implements ServerResource { } } + private Answer execute(GlobalLoadBalancerConfigCommand gslbCmd, int numRetries) { + + String lbMethod = gslbCmd.getLoadBalancerMethod(); + String persistenceType = gslbCmd.getPersistenceType(); + String serviceType = gslbCmd.getServiceType(); + boolean forRevoke = gslbCmd.isForRevoke(); + long gslbId = gslbCmd.getGslbId(); + List sites = gslbCmd.getSiteDetails(); + + String domainName = gslbCmd.getDomainName(); + String vserverName = GSLB.generateVirtualServerName(domainName); + + try { + + if (!forRevoke) { //check if the global load balancer rule is being added + + // Add a GSLB virtual server + GSLB.createVirtualServer(_netscalerService, vserverName, lbMethod, persistenceType, gslbId, serviceType); + + if (sites != null) { // check if there are any sites that are participating in global load balancing + for (SiteLoadBalancerConfig site : sites) { + + String sitePrivateIP = site.getGslbProviderPrivateIp(); + String sitePublicIP = site.getGslbProviderPublicIp(); + String servicePublicIp = site.getServicePublicIp(); + String servicePublicPort = site.getServicePort(); + String siteName = GSLB.generateUniqueSiteName(sitePrivateIP, sitePublicIP, site.getDataCenterId()); + + // Add/Delete GSLB local and remote sites that are part of GSLB virtual server + if (!site.forRevoke()) { + String siteType = (site.isLocal()) ? "LOCAL" : "REMOTE"; + if (GSLB.getSiteObject(_netscalerService, siteName) != null) { + GSLB.updateSite(_netscalerService, siteType, siteName, site.getGslbProviderPrivateIp(), + site.getGslbProviderPublicIp()); + } else { + GSLB.createSite(_netscalerService, siteName, siteType, site.getGslbProviderPrivateIp(), + site.getGslbProviderPublicIp()); + } + } + + // Add/Delete GSLB service corresponding the service running on each site + String serviceName = GSLB.generateUniqueServiceName(siteName, servicePublicIp, servicePublicPort); + if (!site.forRevoke()) { + // create a 'gslbservice' object + GSLB.createService(_netscalerService, serviceName, site.getServiceType(), + servicePublicIp, servicePublicPort, siteName); + + // Bind 'gslbservice' service object to GSLB virtual server + GSLB.createVserverServiceBinding(_netscalerService, serviceName, vserverName); + + } else { + // Unbind GSLB service with GSLB virtual server + GSLB.deleteVserverServiceBinding(_netscalerService, serviceName, vserverName); + + // delete 'gslbservice' object + gslbservice service = GSLB.getServiceObject(_netscalerService, serviceName); + GSLB.deleteService(_netscalerService, serviceName); + } + + if (site.forRevoke()) { // delete the site if its for revoke + GSLB.deleteSite(_netscalerService, siteName); + } + } + } + + // Bind GSLB vserver to domain + GSLB.createVserverDomainBinding(_netscalerService, vserverName, domainName); + + } else { // global load balancer rule is being deleted, so clean up all objects created + + // remove binding between virtual server and the domain name + GSLB.deleteVserverDomainBinding(_netscalerService, vserverName, domainName); + + if (sites != null) { + for (SiteLoadBalancerConfig site : sites) { + + String sitePrivateIP = site.getGslbProviderPrivateIp(); + String sitePublicIP = site.getGslbProviderPublicIp(); + String servicePublicIp = site.getServicePublicIp(); + String servicePublicPort = site.getServicePort(); + String siteName = GSLB.generateUniqueSiteName(sitePrivateIP, sitePublicIP, site.getDataCenterId()); + + // remove binding between virtual server and services + String serviceName = GSLB.generateUniqueServiceName(siteName, servicePublicIp, servicePublicPort); + GSLB.deleteVserverServiceBinding(_netscalerService, serviceName, vserverName); + + // delete service object + GSLB.deleteService(_netscalerService, serviceName); + + // delete GSLB site object + GSLB.deleteSite(_netscalerService, siteName); + } + } + + // delete GSLB virtual server + GSLB.deleteVirtualServer(_netscalerService, vserverName); + } + + saveConfiguration(); + + } catch (Exception e) { + String errMsg = "Failed to apply GSLB configuration due to " + e.getMessage(); + if (shouldRetry(numRetries)) { + return retry(gslbCmd, numRetries); + } + return new GlobalLoadBalancerConfigAnswer(false, errMsg); + } + + return new GlobalLoadBalancerConfigAnswer(true, "Successfully applied GSLB configuration."); + } + + /* + * convenience class to create/update/delete/get the GSLB specific NetScaler objects + * - gslbsite + * - gslbvserver + * - gslbservice + * - vserver-service binding + * - vserver-domain bindings + */ + private static class GSLB { + + // create a 'gslbsite' object representing a site + private static void createSite(nitro_service client, String siteName, + String siteType, String siteIP, String sitePublicIP) throws ExecutionException{ + try { + gslbsite site; + site = getSiteObject(client, siteName); + + boolean isUpdateSite = false; + if (site == null) { + site = new gslbsite(); + } else { + isUpdateSite = true; + } + + assert("LOCAL".equalsIgnoreCase(siteType) || "REMOTE".equalsIgnoreCase(siteType)); + site.set_sitetype(siteType); + site.set_sitename(siteName); + site.set_siteipaddress(siteIP); + site.set_publicip(sitePublicIP); + site.set_metricexchange("ENABLED"); + site.set_nwmetricexchange("ENABLED"); + site.set_sessionexchange("ENABLED"); + if (isUpdateSite) { + gslbsite.update(client, site); + } else { + gslbsite.add(client, site); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully created GSLB site: " + siteName); + } + } catch (Exception e) { + String errMsg = "Failed to create GSLB site: " + siteName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // delete 'gslbsite' object representing a site + private static void deleteSite(nitro_service client, String siteName) throws ExecutionException{ + try { + gslbsite site = getSiteObject(client, siteName); + if (site != null) { + gslbsite_gslbservice_binding[] serviceBindings = gslbsite_gslbservice_binding.get(client, siteName); + if (serviceBindings != null && serviceBindings.length > 0) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("There are services associated with GSLB site: " + + siteName + " so ignoring site deletion"); + } + } + gslbsite.delete(client, siteName); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully deleted GSLB site: " + siteName); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.warn("Ignoring delete request for non existing GSLB site: " + siteName); + } + } + } catch (Exception e) { + String errMsg = "Failed to delete GSLB site: " + siteName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // update 'gslbsite' object representing a site + private static void updateSite(nitro_service client, String siteType, String siteName, + String siteIP, String sitePublicIP) throws ExecutionException { + try { + gslbsite site; + site = getSiteObject(client, siteName); + if (site == null) { + if (s_logger.isDebugEnabled()) { + s_logger.warn("Ignoring update request for non existing GSLB site: " + siteName); + } + return; + } + assert ("LOCAL".equalsIgnoreCase(siteType) || "REMOTE".equalsIgnoreCase(siteType)); + site.set_sitetype(siteType); + site.set_sitename(siteName); + site.set_siteipaddress(siteIP); + site.set_publicip(sitePublicIP); + site.set_metricexchange("ENABLED"); + site.set_nwmetricexchange("ENABLED"); + site.set_sessionexchange("ENABLED"); + gslbsite.update(client, site); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully updated GSLB site: " + siteName); + } + + } catch (Exception e) { + String errMsg = "Failed to update GSLB site: " + siteName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // create a 'gslbvserver' object representing a globally load balanced service + private static void createVirtualServer(nitro_service client, String vserverName, String lbMethod, + String persistenceType, long persistenceId, String serviceType) + throws ExecutionException { + try { + gslbvserver vserver; + vserver = getVserverObject(client, vserverName); + + boolean isUpdateSite = false; + if (vserver == null) { + vserver = new gslbvserver(); + } else { + isUpdateSite = true; + } + + vserver.set_name(vserverName); + vserver.set_lbmethod(lbMethod); + vserver.set_persistencetype(persistenceType); + if ("SOURCEIP".equalsIgnoreCase(persistenceType)) { + vserver.set_persistenceid(persistenceId); + } + vserver.set_servicetype(serviceType); + vserver.set_state("ENABLED"); + vserver.set_cookietimeout(null); + vserver.set_domainname(null); + if (isUpdateSite) { + if ("roundrobin".equalsIgnoreCase(lbMethod)) { + vserver.set_netmask(null); + vserver.set_v6netmasklen(null); + } + gslbvserver.update(client, vserver); + } else { + gslbvserver.add(client, vserver); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully added GSLB virtual server: " + vserverName); + } + + } catch (Exception e) { + String errMsg = "Failed to add GSLB virtual server: " + vserverName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // delete 'gslbvserver' object representing a globally load balanced service + private static void deleteVirtualServer(nitro_service client, String vserverName) throws ExecutionException { + try { + gslbvserver vserver = getVserverObject(client, vserverName); + if (vserver != null) { + gslbvserver.delete(client, vserver); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully deleted GSLB virtual server: " + vserverName); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.warn("Ignoring delete request for non existing GSLB virtual server: " + vserverName); + } + } + } catch (Exception e) { + String errMsg = "Failed to delete GSLB virtual server: " + vserverName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // enable 'gslbvserver' object representing a globally load balanced service + private static void enableVirtualServer(nitro_service client, String vserverName) throws ExecutionException { + try { + gslbvserver vserver = getVserverObject(client, vserverName); + if (vserver != null) { + gslbvserver.enable(client, vserver); + } + } catch (Exception e) { + String errMsg = "Failed to enable GSLB virtual server: " + vserverName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // disable 'gslbvserver' object representing a globally load balanced service + private static void disableVirtualServer(nitro_service client, String vserverName) throws ExecutionException{ + try { + gslbvserver vserver = getVserverObject(client, vserverName); + if (vserver != null) { + gslbvserver.disable(client, vserver); + } + } catch (Exception e) { + String errMsg = "Failed to disable GSLB virtual server: " + vserverName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // update 'gslbvserver' object representing a globally load balanced service + private static void updateVirtualServer(nitro_service client, String vserverName, String lbMethod, + String persistenceType, String serviceType) throws ExecutionException { + try { + gslbvserver vServer = getVserverObject(client, vserverName); + if (vServer != null) { + vServer.set_lbmethod(lbMethod); + vServer.set_persistencetype(persistenceType); + vServer.set_servicetype(serviceType); + gslbvserver.update(client, vServer); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully updated GSLB virtual server: " + vserverName); + } + } + } catch (Exception e) { + String errMsg = "Failed to update GSLB virtual server: " + vserverName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // create, delete, update, get the GSLB services + private static void createService(nitro_service client, String serviceName, String serviceType, String serviceIp, + String servicePort, String siteName) throws ExecutionException{ + try { + gslbservice service; + service = getServiceObject(client, serviceName); + + boolean isUpdateSite = false; + if (service == null) { + service = new gslbservice(); + } else { + isUpdateSite = true; + } + + service.set_sitename(siteName); + service.set_servername(serviceIp); + int port = Integer.parseInt(servicePort); + service.set_port(port); + service.set_servicename(serviceName); + service.set_servicetype(serviceType); + if (isUpdateSite) { + service.set_viewip(null); + service.set_viewname(null); + gslbservice.update(client, service); + } else { + gslbservice.add(client, service); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully created service: " + serviceName + " at site: " + siteName); + } + } catch (Exception e) { + String errMsg = "Failed to created service: " + serviceName + " at site: " + siteName; + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + private static void deleteService(nitro_service client, String serviceName) throws ExecutionException { + try { + gslbservice service = getServiceObject(client, serviceName); + if (service != null) { + gslbservice.delete(client, serviceName); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully deleted service: " + serviceName); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.warn("Ignoring delete request for non existing service: " + serviceName); + } + } + } catch (Exception e) { + String errMsg = "Failed to delete service: " + serviceName + " due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + private static void updateService(nitro_service client, String serviceName, String serviceType, String publicIp, + String publicPort, String siteName) throws ExecutionException { + try { + gslbservice service; + service = getServiceObject(client, serviceName); + + if (service != null) { + service.set_sitename(siteName); + service.set_publicip(publicIp); + service.set_publicport(Integer.getInteger(publicPort)); + service.set_servicename(serviceName); + service.set_servicetype(serviceType); + gslbservice.update(client, service); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully updated service: " + serviceName + " at site: " + siteName); + } + } + } catch (Exception e) { + String errMsg = "Failed to update service: " + serviceName + " at site: " + siteName; + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + private static void createVserverServiceBinding(nitro_service client, String serviceName, String vserverName) + throws ExecutionException { + try { + gslbvserver_gslbservice_binding binding = new gslbvserver_gslbservice_binding(); + binding.set_name(vserverName); + binding.set_servicename(serviceName); + gslbvserver_gslbservice_binding.add(client, binding); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully created service: " + serviceName + " and virtual server: " + + vserverName + " binding"); + } + } catch (Exception e) { + String errMsg = "Failed to create service: " + serviceName + " and virtual server: " + + vserverName + " binding due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + private static void deleteVserverServiceBinding(nitro_service client, String serviceName, String vserverName) + throws ExecutionException { + try { + gslbvserver_gslbservice_binding[] bindings = gslbvserver_gslbservice_binding.get(client, vserverName); + if (bindings != null) { + for (gslbvserver_gslbservice_binding binding: bindings) { + if (binding.get_servicename().equalsIgnoreCase(serviceName) && + binding.get_name().equals(vserverName)) { + gslbvserver_gslbservice_binding.delete(client, binding); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully deleted service: " + serviceName + " and virtual server: " + + vserverName + " binding"); + } + break; + } + } + } + } catch (Exception e) { + String errMsg = "Failed to create service: " + serviceName + " and virtual server: " + + vserverName + " binding due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // create, delete GSLB virtual server and domain bindings + private static void createVserverDomainBinding(nitro_service client, String vserverName, String domainName) + throws ExecutionException { + String errMsg; + try { + gslbvserver_domain_binding binding = new gslbvserver_domain_binding(); + binding.set_domainname(domainName); + binding.set_name(vserverName); + gslbvserver_domain_binding.add(client, binding); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully added virtual server: " + + vserverName + " domain name: " + domainName + " binding"); + } + return; + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_GSLB_DOMAIN_ALREADY_BOUND) { + return; + } + errMsg = e.getMessage(); + } catch (Exception e) { + errMsg = e.getMessage(); + } + errMsg = "Failed to create virtual server: " + vserverName + " domain name: " + domainName + " binding" + errMsg; + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + + private static void deleteVserverDomainBinding(nitro_service client, String vserverName, String domainName) + throws ExecutionException { + try { + gslbvserver_domain_binding[] bindings = gslbvserver_domain_binding.get(client, vserverName); + if (bindings != null) { + for (gslbvserver_domain_binding binding: bindings) { + if (binding.get_domainname().equalsIgnoreCase(domainName)) { + gslbvserver_domain_binding.delete(client, binding); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Successfully deleted virtual server: " + vserverName + " and " + + " domain: " + domainName + " binding"); + } + break; + } + } + } + } catch (Exception e) { + String errMsg = "Failed to delete virtual server: " + + vserverName + " and domain " + domainName +" binding due to " + e.getMessage(); + if (s_logger.isDebugEnabled()) { + s_logger.debug(errMsg); + } + throw new ExecutionException(errMsg); + } + } + + // get 'gslbsite' object corresponding to a site name + private static gslbsite getSiteObject(nitro_service client, String siteName) { + try { + gslbsite site = gslbsite.get(client, siteName); + if (site != null) { + return site; + } + } catch (Exception e) { + + } + return null; + } + + private static gslbvserver getVserverObject(nitro_service client, String vserverName) { + try { + gslbvserver vserver = gslbvserver.get(client, vserverName); + return vserver; + } catch (Exception e) { + return null; + } + } + + private static gslbservice getServiceObject(nitro_service client, String serviceName) { + try { + gslbservice service = gslbservice.get(client, serviceName); + return service; + } catch (Exception e) { + return null; + } + } + + private static String generateUniqueSiteName(String sitePrivateIp, String sitePublicIP, long dataCenterId) { + return "cloudsite" + String.valueOf(dataCenterId); + } + + private static String generateVirtualServerName(String domainName) { + return "cloud-gslb-vserver-" + domainName; + } + + private static String generateUniqueServiceName(String siteName, String publicIp, String publicPort) { + return "cloud-gslb-service-" + siteName + "-" + publicIp + "-" + publicPort; + } + } + + private void enableVPXInterfaces(String publicIf, String privateIf, ns ns_obj) { // enable VPX to use 10 gigabit Ethernet interfaces if public/private interface // on SDX is a 10Gig interface diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 663139da41f..f33601f76ec 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -117,29 +117,12 @@ import com.cloud.event.Event; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkProfile; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.Site2SiteCustomerGateway; -import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.Site2SiteVpnGateway; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.network.VpnUser; -import com.cloud.network.as.AutoScalePolicy; -import com.cloud.network.as.AutoScaleVmGroup; -import com.cloud.network.as.AutoScaleVmProfile; -import com.cloud.network.as.AutoScaleVmProfileVO; -import com.cloud.network.as.Condition; -import com.cloud.network.as.ConditionVO; -import com.cloud.network.as.Counter; +import com.cloud.network.as.*; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkVO; @@ -168,6 +151,7 @@ import com.cloud.org.Cluster; import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectInvitation; +import com.cloud.region.ha.GlobalLoadBalancerRule; import com.cloud.server.Criteria; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; @@ -220,6 +204,7 @@ import com.cloud.vm.snapshot.VMSnapshot; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.response.VMSnapshotResponse; import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import java.text.DecimalFormat; import java.util.*; @@ -684,6 +669,19 @@ public class ApiResponseHelper implements ResponseGenerator { return lbResponse; } + @Override + public GlobalLoadBalancerResponse createGlobalLoadBalancerResponse(GlobalLoadBalancerRule globalLoadBalancerRule) { + GlobalLoadBalancerResponse response = new GlobalLoadBalancerResponse(); + response.setAlgorithm(globalLoadBalancerRule.getAlgorithm()); + response.setStickyMethod(globalLoadBalancerRule.getPersistence()); + response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain()); + response.setName(globalLoadBalancerRule.getName()); + response.setDescription(globalLoadBalancerRule.getDescription()); + response.setRegionIdId(globalLoadBalancerRule.getRegion()); + response.setId(globalLoadBalancerRule.getUuid()); + return response; + } + @Override public PodResponse createPodResponse(Pod pod, Boolean showCapacities) { String[] ipRange = new String[2]; diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 0439c6e2cc9..3c0857568b4 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -16,51 +16,39 @@ // under the License. package com.cloud.api; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.security.SecureRandom; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import javax.annotation.PostConstruct; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - +import com.cloud.api.response.ApiResponseSerializer; +import com.cloud.async.AsyncCommandQueued; +import com.cloud.async.AsyncJob; +import com.cloud.async.AsyncJobManager; +import com.cloud.async.AsyncJobVO; +import com.cloud.configuration.Config; +import com.cloud.configuration.ConfigurationVO; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.domain.Domain; +import com.cloud.domain.DomainVO; +import com.cloud.event.ActionEventUtils; +import com.cloud.exception.*; +import com.cloud.user.*; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.component.PluggableService; +import com.cloud.utils.concurrency.NamedThreadFactory; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.acl.APIChecker; -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; -import org.apache.cloudstack.api.BaseCmd; -import org.apache.cloudstack.api.BaseListCmd; -import org.apache.cloudstack.api.ResponseObject; -import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; -import com.cloud.event.ActionEventUtils; -import org.apache.cloudstack.acl.APILimitChecker; -import org.apache.cloudstack.api.*; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; +import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; +import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectInvitationsCmd; import org.apache.cloudstack.api.command.user.project.ListProjectsCmd; import org.apache.cloudstack.api.command.user.securitygroup.ListSecurityGroupsCmd; @@ -68,17 +56,12 @@ import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; +import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; import org.apache.cloudstack.api.response.ExceptionResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; +import org.apache.cloudstack.region.RegionManager; import org.apache.commons.codec.binary.Base64; -import org.apache.http.ConnectionClosedException; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpResponse; -import org.apache.http.HttpServerConnection; -import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; +import org.apache.http.*; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.entity.BasicHttpEntity; import org.apache.http.impl.DefaultHttpResponseFactory; @@ -89,57 +72,29 @@ import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.BasicHttpProcessor; -import org.apache.http.protocol.HttpContext; -import org.apache.http.protocol.HttpRequestHandler; -import org.apache.http.protocol.HttpRequestHandlerRegistry; -import org.apache.http.protocol.HttpService; -import org.apache.http.protocol.ResponseConnControl; -import org.apache.http.protocol.ResponseContent; -import org.apache.http.protocol.ResponseDate; -import org.apache.http.protocol.ResponseServer; +import org.apache.http.protocol.*; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; -import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; -import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import com.cloud.api.response.ApiResponseSerializer; -import org.apache.cloudstack.region.RegionManager; - -import com.cloud.async.AsyncCommandQueued; -import com.cloud.async.AsyncJob; -import com.cloud.async.AsyncJobManager; -import com.cloud.async.AsyncJobVO; -import com.cloud.configuration.Config; -import com.cloud.configuration.ConfigurationVO; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.domain.Domain; -import com.cloud.domain.DomainVO; -import com.cloud.exception.AccountLimitException; -import com.cloud.exception.CloudAuthenticationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.RequestLimitException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.DomainManager; -import com.cloud.user.User; -import com.cloud.user.UserAccount; -import com.cloud.user.UserContext; -import com.cloud.user.UserVO; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.Pair; -import com.cloud.utils.StringUtils; -import com.cloud.utils.component.ComponentContext; -import com.cloud.utils.component.PluggableService; -import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; -import com.cloud.utils.exception.CloudRuntimeException; +import javax.annotation.PostConstruct; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.inject.Inject; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.net.*; +import java.security.SecureRandom; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; @Component public class ApiServer implements HttpRequestHandler, ApiServerService { @@ -208,11 +163,11 @@ public class ApiServer implements HttpRequestHandler, ApiServerService { for(PluggableService pluggableService: _pluggableServices) cmdClasses.addAll(pluggableService.getCommands()); - for(Class cmdClass: cmdClasses) { - APICommand at = cmdClass.getAnnotation(APICommand.class); - if (at == null) { + for(Class cmdClass: cmdClasses) { + APICommand at = cmdClass.getAnnotation(APICommand.class); + if (at == null) { throw new CloudRuntimeException(String.format("%s is claimed as a API command, but it doesn't have @APICommand annotation", cmdClass.getName())); - } + } String apiName = at.name(); if (_apiNameCmdClassMap.containsKey(apiName)) { s_logger.error("API Cmd class " + cmdClass.getName() + " has non-unique apiname" + apiName); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 9db7dbdd89b..1a57a64488d 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -36,6 +36,10 @@ import com.cloud.template.TemplateManager; import com.cloud.vm.UserVmManager; import com.cloud.vm.snapshot.VMSnapshotManager; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + public enum Config { // Alert @@ -387,7 +391,9 @@ public enum Config { VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "600", "In second, timeout for create vm snapshot", null), VMSnapshotExpungeInterval("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.expunge.interval", "60", "The interval (in seconds) to wait before running the expunge thread.", null), - VMSnapshotExpungeWorkers("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.expunge.workers", "1", "Number of workers performing expunge ", null); + VMSnapshotExpungeWorkers("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.expunge.workers", "1", "Number of workers performing expunge ", null), + + CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", "default", " DNS name of the cloud", null); private final String _category; diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java index dee3ca966e9..9f11b850180 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java @@ -47,7 +47,9 @@ public interface ExternalLoadBalancerDeviceManager extends Manager{ * @param server resource that will handle the commands specific to this device * @return Host object for the device added */ - public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource); + public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, String username, + String password, String deviceName, ServerResource resource, boolean gslbProvider, + String gslbSitePublicIp, String gslbSitePrivateIp); /** * deletes load balancer device added in to a physical network diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index b2a56fc056c..cafe95aeb87 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -122,6 +122,15 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicVO; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.response.ExternalLoadBalancerResponse; +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import org.apache.log4j.Logger; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.URI; +import java.util.*; public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase implements ExternalLoadBalancerDeviceManager, ResourceStateAdapter { @@ -189,7 +198,9 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase @Override @DB - public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, String username, String password, String deviceName, ServerResource resource) { + public ExternalLoadBalancerDeviceVO addExternalLoadBalancer(long physicalNetworkId, String url, + String username, String password, String deviceName, ServerResource resource, boolean gslbProvider, + String gslbSitePublicIp, String gslbSitePrivateIp) { PhysicalNetworkVO pNetwork = null; NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); @@ -204,15 +215,25 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase if (pNetwork == null) { throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); } - zoneId = pNetwork.getDataCenterId(); + zoneId = pNetwork.getDataCenterId(); PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); - if (ntwkSvcProvider == null) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + - " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); - } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + - " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); + + if (gslbProvider) { + ExternalLoadBalancerDeviceVO zoneGslbProvider = _externalLoadBalancerDeviceDao.findGslbServiceProvider( + physicalNetworkId, ntwkDevice.getNetworkServiceProvder()); + if (zoneGslbProvider != null) { + throw new CloudRuntimeException("There is a GSLB service provider configured in the zone alredy."); + } + } else { + ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + + " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); + } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + + " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); + } } URI uri; @@ -253,11 +274,15 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase capacity = _defaultLbCapacity; } + ExternalLoadBalancerDeviceVO lbDeviceVO; txn.start(); - ExternalLoadBalancerDeviceVO lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), - deviceName, capacity, dedicatedUse); + lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkDevice.getNetworkServiceProvder(), + deviceName, capacity, dedicatedUse, gslbProvider); _externalLoadBalancerDeviceDao.persist(lbDeviceVO); - + if (!gslbProvider) { + lbDeviceVO.setGslbSitePrivateIP(gslbSitePublicIp); + lbDeviceVO.setGslbSitePrivateIP(gslbSitePrivateIp); + } DetailVO hostDetail = new DetailVO(host.getId(), ApiConstants.LOAD_BALANCER_DEVICE_ID, String.valueOf(lbDeviceVO.getId())); _hostDetailDao.persist(hostDetail); @@ -501,7 +526,9 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase "&publicipvlan=" + publicIPVlanTag + "&publicipgateway=" + publicIPgateway; ExternalLoadBalancerDeviceVO lbAppliance = null; try { - lbAppliance = addExternalLoadBalancer(physicalNetworkId, url, username, password, createLbAnswer.getDeviceName(), createLbAnswer.getServerResource()); + lbAppliance = addExternalLoadBalancer(physicalNetworkId, url, username, password, + createLbAnswer.getDeviceName(), createLbAnswer.getServerResource(), false, + null, null); } catch (Exception e) { s_logger.error("Failed to add load balancer appliance in to cloudstack due to " + e.getMessage() + ". So provisioned load balancer appliance will be destroyed."); } diff --git a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java index 1bd210710f3..b7baa7e19ba 100644 --- a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java +++ b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDao.java @@ -16,12 +16,12 @@ // under the License. package com.cloud.network.dao; -import java.util.List; - import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.utils.db.GenericDao; +import java.util.List; + public interface ExternalLoadBalancerDeviceDao extends GenericDao { /** @@ -64,4 +64,11 @@ public interface ExternalLoadBalancerDeviceDao extends GenericDao listByProviderAndManagedType(long physicalNetworkId, String provider_name, boolean managed); + + /** + * Find the external load balancer device that is provisioned as GSLB service provider in the pyshical network + * @param physicalNetworkId physical Network Id + * @return ExternalLoadBalancerDeviceVO for the device acting as GSLB provider in the physical network + */ + ExternalLoadBalancerDeviceVO findGslbServiceProvider(long physicalNetworkId, String providerName); } diff --git a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java index e559fad3a1e..ea6437dc2c3 100644 --- a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java +++ b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceDaoImpl.java @@ -16,11 +16,6 @@ // 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.dao.ExternalLoadBalancerDeviceVO.LBDeviceAllocationState; import com.cloud.network.dao.ExternalLoadBalancerDeviceVO.LBDeviceState; import com.cloud.utils.db.DB; @@ -28,6 +23,10 @@ import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.List; @Component @Local(value=ExternalLoadBalancerDeviceDao.class) @DB(txn=false) @@ -37,6 +36,7 @@ public class ExternalLoadBalancerDeviceDaoImpl extends GenericDaoBase allocationStateSearch; final SearchBuilder deviceStatusSearch; final SearchBuilder deviceManagedTypeSearch; + final SearchBuilder gslbProviderSearch; public ExternalLoadBalancerDeviceDaoImpl() { super(); @@ -67,6 +67,12 @@ public class ExternalLoadBalancerDeviceDaoImpl extends GenericDaoBase listByPhysicalNetwork(long physicalNetworkId) { @@ -109,4 +115,13 @@ public class ExternalLoadBalancerDeviceDaoImpl extends GenericDaoBase sc = gslbProviderSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("providerName", providerName); + sc.setParameters("gslbProvider", true); + return findOneBy(sc); + } } diff --git a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java index cd9dffd8f94..04714a6a4de 100644 --- a/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java +++ b/server/src/com/cloud/network/dao/ExternalLoadBalancerDeviceVO.java @@ -20,17 +20,9 @@ import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.network.ExternalNetworkDeviceManager; +import javax.persistence.*; import java.util.UUID; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; - /** * ExternalLoadBalancerDeviceVO contains information on external load balancer devices (F5/Netscaler VPX,MPX,SDX) added into a deployment */ @@ -73,6 +65,15 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity @Column(name="is_dedicated") private boolean isDedicatedDevice; + @Column(name="is_gslb_provider") + private boolean gslbProvider; + + @Column(name="gslb_site_publicip") + private String gslbSitePublicIP; + + @Column(name="gslb_site_privateip") + private String gslbSitePrivateIP; + @Column(name = "parent_host_id") private long parentHostId; @@ -93,7 +94,7 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity } public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, - long capacity, boolean dedicated) { + long capacity, boolean dedicated, boolean gslbProvider) { this.physicalNetworkId = physicalNetworkId; this.providerName = provider_name; this.deviceName = device_name; @@ -105,7 +106,9 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity this.isManagedDevice = false; this.state = LBDeviceState.Enabled; this.uuid = UUID.randomUUID().toString(); - + this.gslbProvider = gslbProvider; + this.gslbSitePublicIP = null; + this.gslbSitePrivateIP = null; if (device_name.equalsIgnoreCase(ExternalNetworkDeviceManager.NetworkDevice.NetscalerSDXLoadBalancer.getName())) { this.allocationState = LBDeviceAllocationState.Provider; } @@ -113,7 +116,7 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, long capacity, boolean dedicated, boolean managed, long parentHostId) { - this(hostId, physicalNetworkId, provider_name, device_name, capacity, dedicated); + this(hostId, physicalNetworkId, provider_name, device_name, capacity, dedicated, false); this.isManagedDevice = managed; this.parentHostId = parentHostId; } @@ -190,6 +193,30 @@ public class ExternalLoadBalancerDeviceVO implements InternalIdentity, Identity isDedicatedDevice = isDedicated; } + public boolean getGslbProvider() { + return gslbProvider; + } + + public void setGslbProvider(boolean gslbProvider) { + gslbProvider = gslbProvider; + } + + public void setGslbSitePublicIP(String gslbSitePublicIP) { + this.gslbSitePublicIP = gslbSitePublicIP; + } + + public String getGslbSitePublicIP() { + return gslbSitePublicIP; + } + + public void setGslbSitePrivateIP(String gslbSitePrivateIP) { + this.gslbSitePrivateIP = gslbSitePrivateIP; + } + + public String getGslbSitePrivateIP() { + return gslbSitePrivateIP; + } + public String getUuid() { return uuid; } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 80e75cd3d66..7ad1070e1c7 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -16,35 +16,6 @@ // under the License. package com.cloud.network.lb; -import java.security.InvalidParameterException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -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; -import org.apache.cloudstack.api.command.user.loadbalancer.UpdateLoadBalancerRuleCmd; -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; @@ -56,72 +27,24 @@ import com.cloud.dc.dao.VlanDao; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.NetworkRuleConflictException; -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.exception.*; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkManager; -import com.cloud.network.NetworkModel; -import com.cloud.network.NetworkRuleApplier; -import com.cloud.network.as.AutoScalePolicy; -import com.cloud.network.as.AutoScalePolicyConditionMapVO; -import com.cloud.network.as.AutoScaleVmGroup; -import com.cloud.network.as.AutoScaleVmGroupPolicyMapVO; -import com.cloud.network.as.AutoScaleVmGroupVO; -import com.cloud.network.as.AutoScaleVmProfile; +import com.cloud.network.as.*; import com.cloud.network.as.Condition; -import com.cloud.network.as.Counter; -import com.cloud.network.as.dao.AutoScalePolicyConditionMapDao; -import com.cloud.network.as.dao.AutoScalePolicyDao; -import com.cloud.network.as.dao.AutoScaleVmGroupDao; -import com.cloud.network.as.dao.AutoScaleVmGroupPolicyMapDao; -import com.cloud.network.as.dao.AutoScaleVmProfileDao; -import com.cloud.network.as.dao.ConditionDao; -import com.cloud.network.as.dao.CounterDao; -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; -import com.cloud.network.dao.LoadBalancerVMMapDao; -import com.cloud.network.dao.LoadBalancerVMMapVO; -import com.cloud.network.dao.LoadBalancerVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.dao.NetworkVO; +import com.cloud.network.as.dao.*; +import com.cloud.network.dao.*; 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.lb.LoadBalancingRule.*; +import com.cloud.network.rules.*; 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; -import com.cloud.network.rules.RulesManager; -import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.NetworkOffering; import com.cloud.projects.Project.ListProjectResourcesCriteria; @@ -130,24 +53,14 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.DomainService; -import com.cloud.user.User; -import com.cloud.user.UserContext; +import com.cloud.user.*; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.JoinBuilder; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; +import com.cloud.utils.db.*; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.Nic; @@ -157,6 +70,16 @@ import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.command.user.loadbalancer.*; +import org.apache.cloudstack.api.response.ServiceResponse; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.security.InvalidParameterException; +import java.util.*; @Component @Local(value = { LoadBalancingRulesManager.class, LoadBalancingRulesService.class }) diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index efdee207f4d..f80e0c25318 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -16,105 +16,6 @@ // under the License. package com.cloud.server; -import java.lang.reflect.Field; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.annotation.PostConstruct; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.ApiConstants; - -import com.cloud.event.ActionEventUtils; -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; - -import org.apache.cloudstack.api.command.admin.account.*; -import org.apache.cloudstack.api.command.admin.autoscale.*; -import org.apache.cloudstack.api.command.admin.cluster.*; -import org.apache.cloudstack.api.command.admin.config.*; -import org.apache.cloudstack.api.command.admin.domain.*; -import org.apache.cloudstack.api.command.admin.host.*; -import org.apache.cloudstack.api.command.admin.ldap.*; -import org.apache.cloudstack.api.command.admin.network.*; -import org.apache.cloudstack.api.command.admin.offering.*; -import org.apache.cloudstack.api.command.admin.pod.*; -import org.apache.cloudstack.api.command.admin.region.*; -import org.apache.cloudstack.api.command.admin.resource.*; -import org.apache.cloudstack.api.command.admin.router.*; -import org.apache.cloudstack.api.command.admin.storage.*; -import org.apache.cloudstack.api.command.admin.swift.*; -import org.apache.cloudstack.api.command.admin.systemvm.*; -import org.apache.cloudstack.api.command.admin.template.*; -import org.apache.cloudstack.api.command.admin.usage.*; -import org.apache.cloudstack.api.command.admin.user.*; -import org.apache.cloudstack.api.command.admin.vlan.*; -import org.apache.cloudstack.api.command.admin.vm.*; -import org.apache.cloudstack.api.command.admin.vpc.*; -import org.apache.cloudstack.api.command.admin.zone.*; -import org.apache.cloudstack.api.command.user.account.*; -import org.apache.cloudstack.api.command.user.address.*; -import org.apache.cloudstack.api.command.user.autoscale.*; -import org.apache.cloudstack.api.command.user.config.*; -import org.apache.cloudstack.api.command.user.event.*; -import org.apache.cloudstack.api.command.user.firewall.*; -import org.apache.cloudstack.api.command.user.guest.*; -import org.apache.cloudstack.api.command.user.iso.*; -import org.apache.cloudstack.api.command.user.job.*; -import org.apache.cloudstack.api.command.user.loadbalancer.*; -import org.apache.cloudstack.api.command.user.nat.*; -import org.apache.cloudstack.api.command.user.network.*; -import org.apache.cloudstack.api.command.user.offering.*; -import org.apache.cloudstack.api.command.user.project.*; -import org.apache.cloudstack.api.command.user.region.*; -import org.apache.cloudstack.api.command.user.resource.*; -import org.apache.cloudstack.api.command.user.securitygroup.*; -import org.apache.cloudstack.api.command.user.snapshot.*; -import org.apache.cloudstack.api.command.user.ssh.*; -import org.apache.cloudstack.api.command.user.tag.*; -import org.apache.cloudstack.api.command.user.template.*; -import org.apache.cloudstack.api.command.user.vm.*; -import org.apache.cloudstack.api.command.user.vmgroup.*; -import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; -import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd; -import org.apache.cloudstack.api.command.user.volume.*; -import org.apache.cloudstack.api.command.user.vpc.*; -import org.apache.cloudstack.api.command.user.vpn.*; -import org.apache.cloudstack.api.command.user.zone.*; -import org.apache.cloudstack.api.response.ExtractResponse; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; -import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; @@ -126,12 +27,7 @@ import com.cloud.alert.AlertManager; import com.cloud.alert.AlertVO; import com.cloud.alert.dao.AlertDao; import com.cloud.api.ApiDBUtils; -import com.cloud.api.query.vo.EventJoinVO; -import com.cloud.async.AsyncJobExecutor; -import com.cloud.async.AsyncJobManager; -import com.cloud.async.AsyncJobResult; -import com.cloud.async.AsyncJobVO; -import com.cloud.async.BaseAsyncJobExecutor; +import com.cloud.async.*; import com.cloud.capacity.Capacity; import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; @@ -144,36 +40,19 @@ import com.cloud.configuration.ConfigurationVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.consoleproxy.ConsoleProxyManagementState; import com.cloud.consoleproxy.ConsoleProxyManager; -import com.cloud.dc.AccountVlanMapVO; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.HostPodVO; -import com.cloud.dc.Pod; -import com.cloud.dc.PodVlanMapVO; -import com.cloud.dc.Vlan; +import com.cloud.dc.*; import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.AccountVlanMapDao; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.PodVlanMapDao; -import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.*; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InternalErrorException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.StorageUnavailableException; +import com.cloud.exception.*; import com.cloud.ha.HighAvailabilityManager; import com.cloud.host.DetailVO; import com.cloud.host.Host; @@ -190,13 +69,7 @@ import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.info.ConsoleProxyInfo; import com.cloud.keystore.KeystoreManager; import com.cloud.network.IpAddress; -import com.cloud.network.as.ConditionVO; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.LoadBalancerDao; -import com.cloud.network.dao.LoadBalancerVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.*; import com.cloud.org.Cluster; import com.cloud.org.Grouping.AllocationState; import com.cloud.projects.Project; @@ -207,26 +80,10 @@ import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.server.auth.UserAuthenticator; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.storage.GuestOS; -import com.cloud.storage.GuestOSCategoryVO; -import com.cloud.storage.GuestOSVO; -import com.cloud.storage.GuestOsCategory; -import com.cloud.storage.Storage; -import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.*; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.StorageManager; -import com.cloud.storage.StoragePool; -import com.cloud.storage.Upload; import com.cloud.storage.Upload.Mode; -import com.cloud.storage.UploadVO; -import com.cloud.storage.Volume; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.DiskOfferingDao; -import com.cloud.storage.dao.GuestOSCategoryDao; -import com.cloud.storage.dao.GuestOSDao; -import com.cloud.storage.dao.UploadDao; -import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.dao.*; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; @@ -236,64 +93,142 @@ import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.template.TemplateManager; import com.cloud.template.VirtualMachineTemplate.TemplateFilter; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.SSHKeyPair; -import com.cloud.user.SSHKeyPairVO; -import com.cloud.user.User; -import com.cloud.user.UserContext; -import com.cloud.user.UserVO; +import com.cloud.user.*; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; -import com.cloud.utils.EnumUtils; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.Pair; -import com.cloud.utils.PasswordGenerator; -import com.cloud.utils.Ternary; -import com.cloud.utils.component.Adapter; -import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.*; import com.cloud.utils.component.ComponentLifecycle; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; -import com.cloud.utils.component.SystemIntegrityChecker; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.crypt.DBEncryptionUtil; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; -import com.cloud.utils.db.GenericDaoBase; -import com.cloud.utils.db.GlobalLock; -import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.*; import com.cloud.utils.db.JoinBuilder.JoinType; -import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.mgmt.JmxUtil; -import com.cloud.utils.mgmt.ManagementBean; import com.cloud.utils.net.MacAddress; import com.cloud.utils.net.NetUtils; import com.cloud.utils.ssh.SSHKeysHelper; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.InstanceGroupVO; -import com.cloud.vm.SecondaryStorageVmVO; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; +import com.cloud.vm.*; import com.cloud.vm.VirtualMachine.State; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.VirtualMachineProfileImpl; -import com.cloud.vm.dao.ConsoleProxyDao; -import com.cloud.vm.dao.DomainRouterDao; -import com.cloud.vm.dao.InstanceGroupDao; -import com.cloud.vm.dao.SecondaryStorageVmDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; - +import com.cloud.vm.dao.*; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; +import org.apache.cloudstack.api.command.admin.account.*; +import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; +import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; +import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; +import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; +import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd; +import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd; +import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; +import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; +import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; +import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; +import org.apache.cloudstack.api.command.admin.domain.*; +import org.apache.cloudstack.api.command.admin.host.*; +import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; +import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; +import org.apache.cloudstack.api.command.admin.network.*; +import org.apache.cloudstack.api.command.admin.offering.*; +import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; +import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; +import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; +import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; +import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; +import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; +import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; +import org.apache.cloudstack.api.command.admin.resource.*; +import org.apache.cloudstack.api.command.admin.router.*; +import org.apache.cloudstack.api.command.admin.storage.*; +import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; +import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; +import org.apache.cloudstack.api.command.admin.systemvm.*; +import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; +import org.apache.cloudstack.api.command.admin.usage.*; +import org.apache.cloudstack.api.command.admin.user.*; +import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; +import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; +import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; +import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; +import org.apache.cloudstack.api.command.admin.vpc.*; +import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; +import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; +import org.apache.cloudstack.api.command.admin.zone.MarkDefaultZoneForAccountCmd; +import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; +import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd; +import org.apache.cloudstack.api.command.user.account.DeleteAccountFromProjectCmd; +import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; +import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; +import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; +import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd; +import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; +import org.apache.cloudstack.api.command.user.autoscale.*; +import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; +import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; +import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd; +import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd; +import org.apache.cloudstack.api.command.user.event.ListEventsCmd; +import org.apache.cloudstack.api.command.user.firewall.*; +import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd; +import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd; +import org.apache.cloudstack.api.command.user.iso.*; +import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; +import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; +import org.apache.cloudstack.api.command.user.loadbalancer.*; +import org.apache.cloudstack.api.command.user.nat.*; +import org.apache.cloudstack.api.command.user.network.*; +import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; +import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; +import org.apache.cloudstack.api.command.user.project.*; +import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; +import org.apache.cloudstack.api.command.user.region.ha.gslb.*; +import org.apache.cloudstack.api.command.user.resource.*; +import org.apache.cloudstack.api.command.user.securitygroup.*; +import org.apache.cloudstack.api.command.user.snapshot.*; +import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd; +import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd; +import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd; +import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; +import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd; +import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd; +import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; +import org.apache.cloudstack.api.command.user.template.*; +import org.apache.cloudstack.api.command.user.vm.*; +import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; +import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd; +import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; +import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; +import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; +import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd; +import org.apache.cloudstack.api.command.user.volume.*; +import org.apache.cloudstack.api.command.user.vpc.*; +import org.apache.cloudstack.api.command.user.vpn.*; +import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.lang.reflect.Field; +import java.net.*; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -2242,6 +2177,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(DeleteAlertsCmd.class); cmdList.add(ArchiveEventsCmd.class); cmdList.add(DeleteEventsCmd.class); + cmdList.add(CreateGlobalLoadBalancerRuleCmd.class); + cmdList.add(DeleteGlobalLoadBalancerRuleCmd.class); + cmdList.add(ListGlobalLoadBalancerRuleCmd.class); + cmdList.add(AssignToGlobalLoadBalancerRuleCmd.class); + cmdList.add(RemoveFromGlobalLoadBalancerRuleCmd.class); cmdList.add(ListStorageProvidersCmd.class); return cmdList; } diff --git a/server/src/org/apache/cloudstack/region/RegionServiceProvider.java b/server/src/org/apache/cloudstack/region/RegionServiceProvider.java new file mode 100755 index 00000000000..ad7e22f84cb --- /dev/null +++ b/server/src/org/apache/cloudstack/region/RegionServiceProvider.java @@ -0,0 +1,25 @@ +/* + * 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.region; + +import com.cloud.utils.component.Adapter; + +public interface RegionServiceProvider extends Adapter { + +} diff --git a/server/src/org/apache/cloudstack/region/RegionVO.java b/server/src/org/apache/cloudstack/region/RegionVO.java index 907c11dff86..6890bc850a8 100644 --- a/server/src/org/apache/cloudstack/region/RegionVO.java +++ b/server/src/org/apache/cloudstack/region/RegionVO.java @@ -36,6 +36,18 @@ public class RegionVO implements Region{ @Column(name="end_point") private String endPoint; + + public boolean getGslbEnabled() { + return gslbEnabled; + } + + public void setGslbEnabled(boolean gslbEnabled) { + this.gslbEnabled = gslbEnabled; + } + + @Column(name="gslb_service_enabled") + private boolean gslbEnabled; + public RegionVO() { } @@ -43,6 +55,7 @@ public class RegionVO implements Region{ this.id = id; this.name = name; this.endPoint = endPoint; + this.gslbEnabled = true; } public int getId() { @@ -65,4 +78,10 @@ public class RegionVO implements Region{ this.endPoint = endPoint; } + + @Override + public boolean checkIfServiceEnabled(Service service) { + return gslbEnabled; + } + } diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java new file mode 100644 index 00000000000..0020f5d4256 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java @@ -0,0 +1,58 @@ +// 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.region.gslb; + +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.List; + +@Component +@Local(value={GlobalLoadBalancerRuleDao.class}) +public class GlobalLoadBalancerDaoImpl extends GenericDaoBase implements GlobalLoadBalancerRuleDao { + + private final SearchBuilder listByDomainSearch; + private final SearchBuilder listByRegionIDSearch; + + public GlobalLoadBalancerDaoImpl() { + listByDomainSearch = createSearchBuilder(); + listByDomainSearch.and("gslbDomain", listByDomainSearch.entity().getGslbDomain(), SearchCriteria.Op.EQ); + listByDomainSearch.done(); + + listByRegionIDSearch = createSearchBuilder(); + listByRegionIDSearch.and("region", listByRegionIDSearch.entity().getRegion(), SearchCriteria.Op.EQ); + listByRegionIDSearch.done(); + } + + @Override + public List listByRegionId(int regionId) { + SearchCriteria sc = listByRegionIDSearch.create(); + sc.setParameters("region", regionId); + return listBy(sc); + } + + @Override + public GlobalLoadBalancerRuleVO findByDomainName(String domainName) { + SearchCriteria sc = listByDomainSearch.create(); + sc.setParameters("gslbDomain", domainName); + return findOneBy(sc); + } +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDao.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDao.java new file mode 100644 index 00000000000..5ce0b403a70 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDao.java @@ -0,0 +1,30 @@ +// 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.region.gslb; + +import com.cloud.utils.db.GenericDao; + +import java.util.List; + +public interface GlobalLoadBalancerLbRuleMapDao extends GenericDao { + + List listByGslbRuleId(long gslbRuleId); + + GlobalLoadBalancerLbRuleMapVO findByGslbRuleIdAndLbRuleId(long gslbRuleId, long lbRuleId); + +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDaoImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDaoImpl.java new file mode 100644 index 00000000000..2a6e72b6913 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapDaoImpl.java @@ -0,0 +1,63 @@ +// 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.region.gslb; + +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import java.util.List; + +@Component +@Local(value={GlobalLoadBalancerLbRuleMapDao.class}) +@DB(txn = false) +public class GlobalLoadBalancerLbRuleMapDaoImpl extends GenericDaoBase implements GlobalLoadBalancerLbRuleMapDao { + + private final SearchBuilder listByGslbRuleId; + private final SearchBuilder listByLbGslbRuleId; + + public GlobalLoadBalancerLbRuleMapDaoImpl() { + listByGslbRuleId = createSearchBuilder(); + listByGslbRuleId.and("gslbLoadBalancerId", listByGslbRuleId.entity().getGslbLoadBalancerId(), SearchCriteria.Op.EQ); + listByGslbRuleId.done(); + + listByLbGslbRuleId = createSearchBuilder(); + listByLbGslbRuleId.and("gslbLoadBalancerId", listByLbGslbRuleId.entity().getGslbLoadBalancerId(), SearchCriteria.Op.EQ); + listByLbGslbRuleId.and("loadBalancerId", listByLbGslbRuleId.entity().getLoadBalancerId(), SearchCriteria.Op.EQ); + listByLbGslbRuleId.done(); + } + + @Override + public List listByGslbRuleId(long gslbRuleId) { + SearchCriteria sc = listByGslbRuleId.create(); + sc.setParameters("gslbLoadBalancerId", gslbRuleId); + return listBy(sc); + } + + @Override + public GlobalLoadBalancerLbRuleMapVO findByGslbRuleIdAndLbRuleId(long gslbRuleId, long lbRuleId) { + SearchCriteria sc = listByLbGslbRuleId.create(); + sc.setParameters("gslbLoadBalancerId", gslbRuleId); + sc.setParameters("loadBalancerId", lbRuleId); + return findOneBy(sc); + } + +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java new file mode 100644 index 00000000000..6a1e17decc3 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerLbRuleMapVO.java @@ -0,0 +1,83 @@ +// 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.region.gslb; + +import org.apache.cloudstack.api.InternalIdentity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name=("global_load_balancer_lb_rule_map")) +public class GlobalLoadBalancerLbRuleMapVO implements InternalIdentity { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="lb_rule_id") + private long loadBalancerId; + + @Column(name="gslb_rule_id") + private long gslbLoadBalancerId; + + @Column(name="revoke") + private boolean revoke = false; + + public GlobalLoadBalancerLbRuleMapVO() { + + } + + public GlobalLoadBalancerLbRuleMapVO(long loadBalancerId, long gslbLoadBalancerId) { + this.loadBalancerId = loadBalancerId; + this.gslbLoadBalancerId = gslbLoadBalancerId; + this.revoke = false; + } + + public long getId() { + return id; + } + + public long getLoadBalancerId() { + return loadBalancerId; + } + + public long getGslbLoadBalancerId() { + return gslbLoadBalancerId; + } + + public void setLoadBalancerId(long loadBalancerId) { + this.loadBalancerId = loadBalancerId; + } + + public void setGslbLoadBalancerId(long gslbLoadBalancerId) { + this.gslbLoadBalancerId = gslbLoadBalancerId; + } + + public boolean isRevoke() { + return revoke; + } + + public void setRevoke(boolean revoke) { + this.revoke = revoke; + } +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java new file mode 100644 index 00000000000..1b44caa444a --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java @@ -0,0 +1,28 @@ +// 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.region.gslb; + +import com.cloud.utils.db.GenericDao; + +import java.util.List; + +public interface GlobalLoadBalancerRuleDao extends GenericDao { + + List listByRegionId(int regionId); + GlobalLoadBalancerRuleVO findByDomainName(String domainName); +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java new file mode 100644 index 00000000000..a70b3056924 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java @@ -0,0 +1,183 @@ +// 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.region.gslb; + +import com.cloud.region.ha.GlobalLoadBalancerRule; + +import javax.persistence.*; +import java.util.UUID; + +@Entity +@Table(name=("global_load_balancing_rules")) +public class GlobalLoadBalancerRuleVO implements GlobalLoadBalancerRule { + + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + long id; + + @Column(name="name") + private String name; + + @Column(name="description", length=4096) + private String description; + + @Column(name="algorithm") + private String algorithm; + + @Column(name="persistence") + private String persistence; + + @Column(name="gslb_domain_name") + private String gslbDomain; + + @Column(name="service_type") + private String serviceType; + + @Column(name="region_id") + private int region; + + @Column(name="account_id") + long accountId; + + @Column(name="domain_id", updatable=false) + long domainId; + + @Column(name="uuid") + String uuid; + + @Enumerated(value=EnumType.STRING) + @Column(name="state") + GlobalLoadBalancerRule.State state; + + public GlobalLoadBalancerRuleVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public GlobalLoadBalancerRuleVO(String name, String description, String gslbDomain, String algorithm, + String persistence, String serviceType, int regionId, long accountId, + long domainId, State state) { + this.name =name; + this.description = description; + this.region = regionId; + this.algorithm = algorithm; + this.gslbDomain = gslbDomain; + this.persistence = persistence; + this.accountId = accountId; + this.domainId = domainId; + this.serviceType = serviceType; + this.uuid = UUID.randomUUID().toString(); + this.state = state; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String getAlgorithm() { + return algorithm; + } + + @Override + public String getPersistence() { + return persistence; + } + + @Override + public int getRegion() { + return region; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public long getDomainId() { + return domainId; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public void setPersistence(String persistence) { + this.persistence = persistence; + } + + @Override + public String getGslbDomain() { + return gslbDomain; + } + + public void setGslbDomain(String gslbDomain) { + this.gslbDomain = gslbDomain; + } + + public void setRegion(int region) { + this.region =region; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return this.uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public void setState(GlobalLoadBalancerRule.State state) { + this.state = state; + } + + @Override + public GlobalLoadBalancerRule.State getState() { + return state; + } +} diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java new file mode 100644 index 00000000000..1d4720e9108 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -0,0 +1,592 @@ +// 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.region.gslb; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand; +import com.cloud.agent.api.routing.SiteLoadBalancerConfig; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.network.dao.*; +import com.cloud.network.element.NetworkElement; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.RulesManager; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.UserContext; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.api.command.user.region.ha.gslb.*; +import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.region.dao.RegionDao; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +@Local(value = {GlobalLoadBalancingRulesService.class}) +public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingRulesService { + + private static final Logger s_logger = Logger.getLogger(GlobalLoadBalancingRulesServiceImpl.class); + + @Inject + AccountManager _accountMgr; + @Inject + GlobalLoadBalancerRuleDao _gslbRuleDao; + @Inject + GlobalLoadBalancerLbRuleMapDao _gslbLbMapDao; + @Inject + RegionDao _regionDao; + @Inject + RulesManager _rulesMgr; + @Inject + LoadBalancerDao _lbDao; + @Inject + NetworkDao _networkDao; + @Inject + ConfigurationDao _globalConfigDao; + @Inject + IPAddressDao _ipAddressDao; + @Inject + AgentManager _agentMgr; + @Inject + protected GslbServiceProvider _gslbProvider; + @Inject + protected List _networkElements; + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_GLOBAL_LOAD_BALANCER_CREATE, eventDescription = "creating global load " + + "balancer rule", create = true) + public GlobalLoadBalancerRule createGlobalLoadBalancerRule(CreateGlobalLoadBalancerRuleCmd newRule) { + + Integer regionId = newRule.getRegionId(); + String algorithm = newRule.getAlgorithm(); + String stickyMethod = newRule.getStickyMethod(); + String name = newRule.getName(); + String description = newRule.getDescription(); + String domainName = newRule.getServiceDomainName(); + String serviceType = newRule.getServiceType(); + + Account gslbOwner = _accountMgr.getAccount(newRule.getEntityOwnerId()); + + if (!GlobalLoadBalancerRule.Algorithm.isValidAlgorithm(algorithm)) { + throw new InvalidParameterValueException("Invalid Algorithm: " + algorithm); + } + + if (!GlobalLoadBalancerRule.Persistence.isValidPersistence(stickyMethod)) { + throw new InvalidParameterValueException("Invalid persistence: " + stickyMethod); + } + + if (!GlobalLoadBalancerRule.ServiceType.isValidServiceType(serviceType)) { + throw new InvalidParameterValueException("Invalid service type: " + serviceType); + } + + if (!NetUtils.verifyDomainName(domainName)){ + throw new InvalidParameterValueException("Invalid domain name : " + domainName); + } + + GlobalLoadBalancerRuleVO gslbRuleWithDomainName = _gslbRuleDao.findByDomainName(domainName); + if (gslbRuleWithDomainName != null) { + throw new InvalidParameterValueException("Domain name " + domainName + "is in use"); + } + + Region region = _regionDao.findById(regionId); + if (region == null) { + throw new InvalidParameterValueException("Invalid region ID: " + regionId); + } + + if (!region.checkIfServiceEnabled(Region.Service.Gslb)) { + throw new CloudRuntimeException("GSLB service is not enabled in region : " + region.getName()); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + GlobalLoadBalancerRuleVO newGslbRule = new GlobalLoadBalancerRuleVO(name, description, domainName, algorithm, + stickyMethod, serviceType, regionId, gslbOwner.getId(), gslbOwner.getDomainId(), + GlobalLoadBalancerRule.State.Staged); + _gslbRuleDao.persist(newGslbRule); + txn.commit(); + + s_logger.debug("successfully created new global load balancer rule for the account " + gslbOwner.getId()); + + return newGslbRule; + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_GLOBAL_LOAD_BALANCER_RULE, eventDescription = + "Assigning a load balancer rule to global load balancer rule", async=true) + public boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd assignToGslbCmd) { + + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + long gslbRuleId = assignToGslbCmd.getGlobalLoadBalancerRuleId(); + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + if (gslbRule == null) { + throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRule.getUuid()); + } + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, gslbRule); + + if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { + throw new InvalidParameterValueException("global load balancer rule id: " + gslbRule.getUuid() + + " is in revoked state"); + } + + List newLbRuleIds = assignToGslbCmd.getLoadBalancerRulesIds(); + if (newLbRuleIds == null || newLbRuleIds.isEmpty()) { + throw new InvalidParameterValueException("empty list of load balancer rule Ids specified to be assigned" + + " global load balancer rule"); + } + + List oldLbRuleIds = new ArrayList(); + List oldZones = new ArrayList(); + List newZones = new ArrayList(oldZones); + + // get the list of load balancer rules id's that are assigned currently to GSLB rule and corresponding zone id's + List gslbLbMapVos = _gslbLbMapDao.listByGslbRuleId(gslbRuleId); + if (gslbLbMapVos != null) { + for (GlobalLoadBalancerLbRuleMapVO gslbLbMapVo : gslbLbMapVos) { + LoadBalancerVO loadBalancer = _lbDao.findById(gslbLbMapVo.getLoadBalancerId()); + Network network = _networkDao.findById(loadBalancer.getNetworkId()); + oldZones.add(network.getDataCenterId()); + oldLbRuleIds.add(gslbLbMapVo.getLoadBalancerId()); + } + } + + /* check each of the load balancer rule id passed in the 'AssignToGlobalLoadBalancerRuleCmd' command is + * valid ID + * caller has access to the rule + * check rule is not revoked + * no two rules are in same zone + * rule is not already assigned to gslb rule + */ + for (Long lbRuleId : newLbRuleIds) { + + LoadBalancerVO loadBalancer = _lbDao.findById(lbRuleId); + if (loadBalancer == null) { + throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); + } + + _accountMgr.checkAccess(caller, null, true, loadBalancer); + + if (loadBalancer.getState() == LoadBalancer.State.Revoke) { + throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is in revoke state"); + } + + if (oldLbRuleIds != null && oldLbRuleIds.contains(loadBalancer.getId())) { + throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is already assigned"); + } + + Network network = _networkDao.findById(loadBalancer.getNetworkId()); + + if (oldZones != null && oldZones.contains(network.getDataCenterId()) || + newZones != null && newZones.contains(network.getDataCenterId())) { + throw new InvalidParameterValueException("Load balancer rule specified should be in unique zone"); + } + + newZones.add(network.getDataCenterId()); + } + + // check each of the zone has a GSLB service provider configured + for (Long zoneId: newZones) { + if (!checkGslbServiceEnabledInZone(zoneId)) { + throw new InvalidParameterValueException("GSLB service is not enabled in the Zone"); + } + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + // persist the mapping for the new Lb rule that needs to assigned to a gslb rule + for (Long lbRuleId : newLbRuleIds) { + GlobalLoadBalancerLbRuleMapVO newGslbLbMap = new GlobalLoadBalancerLbRuleMapVO(); + newGslbLbMap.setGslbLoadBalancerId(gslbRuleId); + newGslbLbMap.setLoadBalancerId(lbRuleId); + _gslbLbMapDao.persist(newGslbLbMap); + } + + // mark the gslb rule state as add + if (gslbRule.getState() == GlobalLoadBalancerRule.State.Staged || gslbRule.getState() == + GlobalLoadBalancerRule.State.Active ) { + gslbRule.setState(GlobalLoadBalancerRule.State.Add); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + } + + txn.commit(); + + boolean success = false; + try { + s_logger.debug("Configuring gslb rule configuration on the gslb service providers in the participating zones"); + + // apply the gslb rule on to the back end gslb service providers on zones participating in gslb + applyGlobalLoadBalancerRuleConfig(gslbRuleId, false); + + // on success set state to Active + gslbRule.setState(GlobalLoadBalancerRule.State.Active); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + + success = true; + + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Failed to apply gslb config"); + } + + return success; + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_REMOVE_FROM_GLOBAL_LOAD_BALANCER_RULE, eventDescription = + "Removing a load balancer rule to be part of global load balancer rule") + public boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRuleCmd removeFromGslbCmd) { + + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + long gslbRuleId = removeFromGslbCmd.getGlobalLoadBalancerRuleId(); + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + if (gslbRule == null) { + throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRule.getUuid()); + } + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, gslbRule); + + if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { + throw new InvalidParameterValueException("global load balancer rule id: " + gslbRuleId + " is already in revoked state"); + } + + List lbRuleIdsToremove = removeFromGslbCmd.getLoadBalancerRulesIds(); + if (lbRuleIdsToremove == null || lbRuleIdsToremove.isEmpty()) { + throw new InvalidParameterValueException("empty list of load balancer rule Ids specified to be un-assigned" + + " to global load balancer rule"); + } + + // get the active list of LB rule id's that are assigned currently to GSLB rule and corresponding zone id's + List oldLbRuleIds = new ArrayList(); + List oldZones = new ArrayList(); + + List gslbLbMapVos = _gslbLbMapDao.listByGslbRuleId(gslbRuleId); + if (gslbLbMapVos == null) { + throw new InvalidParameterValueException(" There are no load balancer rules that are assigned to global " + + " load balancer rule id: " + gslbRule.getUuid() + " that are available for deletion"); + } + + for (Long lbRuleId : lbRuleIdsToremove) { + LoadBalancerVO loadBalancer = _lbDao.findById(lbRuleId); + if (loadBalancer == null) { + throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); + } + + _accountMgr.checkAccess(caller, null, true, loadBalancer); + } + + for (GlobalLoadBalancerLbRuleMapVO gslbLbMapVo : gslbLbMapVos) { + LoadBalancerVO loadBalancer = _lbDao.findById(gslbLbMapVo.getLoadBalancerId()); + Network network = _networkDao.findById(loadBalancer.getNetworkId()); + oldLbRuleIds.add(gslbLbMapVo.getLoadBalancerId()); + oldZones.add(network.getDataCenterId()); + } + + for (Long lbRuleId : lbRuleIdsToremove) { + LoadBalancerVO loadBalancer = _lbDao.findById(lbRuleId); + if (oldLbRuleIds != null && !oldLbRuleIds.contains(loadBalancer.getId())) { + throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is not assigned" + + " to global load balancer rule: " + gslbRule.getUuid()); + } + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + // update the mapping of gslb rule to Lb rule, to revoke state + for (Long lbRuleId : lbRuleIdsToremove) { + GlobalLoadBalancerLbRuleMapVO removeGslbLbMap = _gslbLbMapDao.findByGslbRuleIdAndLbRuleId(gslbRuleId, lbRuleId); + removeGslbLbMap.setRevoke(true); + _gslbLbMapDao.update(removeGslbLbMap.getId(), removeGslbLbMap); + } + + // mark the gslb rule state as add + if (gslbRule.getState() == GlobalLoadBalancerRule.State.Staged) { + gslbRule.setState(GlobalLoadBalancerRule.State.Add); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + } + + txn.commit(); + + boolean success = false; + try { + s_logger.debug("Attempting to configure global load balancer rule configuration on the gslb service providers "); + + // apply the gslb rule on to the back end gslb service providers + applyGlobalLoadBalancerRuleConfig(gslbRuleId, false); + + // on success set state to Active + gslbRule.setState(GlobalLoadBalancerRule.State.Active); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + success = true; + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Failed to update removed load balancer details from gloabal load balancer"); + } + + return success; + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_GLOBAL_LOAD_BALANCER_DELETE, eventDescription = + "Delete global load balancer rule") + public boolean deleteGlobalLoadBalancerRule(DeleteGlobalLoadBalancerRuleCmd deleteGslbCmd) { + + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + long gslbRuleId = deleteGslbCmd.getGlobalLoadBalancerId(); + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + if (gslbRule == null) { + throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); + } + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, gslbRule); + + if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { + throw new InvalidParameterValueException("global load balancer rule id: " + gslbRuleId + " is already in revoked state"); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + List gslbLbMapVos = _gslbLbMapDao.listByGslbRuleId(gslbRuleId); + if (gslbLbMapVos != null) { + //mark all the GSLB-LB mapping to be in revoke state + for (GlobalLoadBalancerLbRuleMapVO gslbLbMap : gslbLbMapVos) { + gslbLbMap.setRevoke(true); + } + } + + //mark the GSlb rule to be in revoke state + gslbRule.setState(GlobalLoadBalancerRule.State.Revoke); + _gslbRuleDao.update(gslbRuleId, gslbRule); + + txn.commit(); + + boolean success = false; + try { + if (gslbLbMapVos != null) { + applyGlobalLoadBalancerRuleConfig(gslbRuleId, true); + } + success = true; + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Failed to update the gloabal load balancer"); + } + + return success; + } + + @Override + public GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalancerRuleCmd updateGslbCmd) { + + String algorithm = updateGslbCmd.getAlgorithm(); + String stickyMethod = updateGslbCmd.getStickyMethod(); + String description = updateGslbCmd.getDescription(); + + long gslbRuleId = updateGslbCmd.getId(); + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + if (gslbRule == null) { + throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); + } + + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, gslbRule); + + + if (!GlobalLoadBalancerRule.Algorithm.isValidAlgorithm(algorithm)) { + throw new InvalidParameterValueException("Invalid Algorithm: " + algorithm); + } + + if (!GlobalLoadBalancerRule.Persistence.isValidPersistence(stickyMethod)) { + throw new InvalidParameterValueException("Invalid persistence: " + stickyMethod); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + gslbRule.setAlgorithm(algorithm); + gslbRule.setPersistence(stickyMethod); + gslbRule.setDescription(description); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + txn.commit(); + + try { + s_logger.debug("Updated global load balancer with id " + gslbRule.getUuid()); + + // apply the gslb rule on to the back end gslb service providers on zones participating in gslb + applyGlobalLoadBalancerRuleConfig(gslbRuleId, false); + + // on success set state to Active + gslbRule.setState(GlobalLoadBalancerRule.State.Active); + _gslbRuleDao.update(gslbRule.getId(), gslbRule); + + return gslbRule; + } catch (ResourceUnavailableException e) { + throw new CloudRuntimeException("Failed to configure gslb config due to " + e.getMessage()); + } + } + + @Override + public List listGlobalLoadBalancerRule(ListGlobalLoadBalancerRuleCmd listGslbCmd) { + Integer regionId = listGslbCmd.getRegionId(); + Long ruleId = listGslbCmd.getId(); + List response = new ArrayList(); + if (regionId == null && ruleId == null) { + throw new InvalidParameterValueException("Invalid arguments. At least one of region id, " + + "rule id must be specified"); + } + + if (regionId != null && ruleId != null) { + throw new InvalidParameterValueException("Invalid arguments. Only one of region id, " + + "rule id must be specified"); + } + + if (ruleId != null) { + GlobalLoadBalancerRule gslbRule = _gslbRuleDao.findById(ruleId); + if (gslbRule == null) { + throw new InvalidParameterValueException("Invalid gslb rule id specified"); + } + response.add(gslbRule); + return response; + } + + if (regionId != null) { + List gslbRules = _gslbRuleDao.listByRegionId(regionId); + if (gslbRules != null) { + response.addAll(gslbRules); + } + return response; + } + + return null; + } + + private boolean applyGlobalLoadBalancerRuleConfig(long gslbRuleId, boolean revoke) throws ResourceUnavailableException { + + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + assert(gslbRule != null); + + String lbMethod = gslbRule.getAlgorithm(); + String persistenceMethod = gslbRule.getPersistence(); + String serviceType = gslbRule.getServiceType(); + + // each Gslb rule will have a FQDN, formed from the domain name associated with the gslb rule + // and the deployment DNS name configured in global config parameter 'cloud.dns.name' + String domainName = gslbRule.getGslbDomain(); + String providerDnsName = _globalConfigDao.getValue(Config.CloudDnsName.key()); + String gslbFqdn = domainName + "." + providerDnsName; + + GlobalLoadBalancerConfigCommand gslbConfigCmd = new GlobalLoadBalancerConfigCommand(gslbFqdn, + lbMethod, persistenceMethod, serviceType, gslbRuleId, revoke); + + // list of the zones participating in global load balancing + List gslbSiteIds = new ArrayList(); + + // map of the zone and info corresponding to the load balancer configured in the zone + Map zoneSiteLoadbalancerMap = new HashMap(); + + List gslbLbMapVos = _gslbLbMapDao.listByGslbRuleId(gslbRuleId); + + assert (gslbLbMapVos != null && !gslbLbMapVos.isEmpty()); + + for (GlobalLoadBalancerLbRuleMapVO gslbLbMapVo : gslbLbMapVos) { + + // get the zone in which load balancer rule is deployed + LoadBalancerVO loadBalancer = _lbDao.findById(gslbLbMapVo.getLoadBalancerId()); + Network network = _networkDao.findById(loadBalancer.getNetworkId()); + long dataCenterId = network.getDataCenterId(); + + gslbSiteIds.add(dataCenterId); + + IPAddressVO ip = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()); + SiteLoadBalancerConfig siteLb = new SiteLoadBalancerConfig(gslbLbMapVo.isRevoke(), serviceType, + ip.getAddress().addr(), Integer.toString(loadBalancer.getDefaultPortStart()), + dataCenterId); + + siteLb.setGslbProviderPublicIp(_gslbProvider.getZoneGslbProviderPublicIp(dataCenterId)); + siteLb.setGslbProviderPrivateIp(_gslbProvider.getZoneGslbProviderPrivateIp(dataCenterId)); + + zoneSiteLoadbalancerMap.put(network.getDataCenterId(), siteLb); + } + + // loop through all the zones, participating in GSLB, and send GSLB config command + // to the corresponding GSLB service provider in that zone + for (long zoneId: gslbSiteIds) { + + List slbs = new ArrayList(); + + // set site as 'local' for the site in that zone + for (long innerLoopZoneId: gslbSiteIds) { + SiteLoadBalancerConfig siteLb = zoneSiteLoadbalancerMap.get(innerLoopZoneId); + siteLb.setLocal(zoneId == innerLoopZoneId); + slbs.add(siteLb); + } + + gslbConfigCmd.setSiteLoadBalancers(slbs); + + try { + _gslbProvider.applyGlobalLoadBalancerRule(zoneId, gslbConfigCmd); + } catch (ResourceUnavailableException e) { + s_logger.warn("Failed to configure GSLB rul in the zone " + zoneId + " due to " + e.getMessage()); + throw new CloudRuntimeException("Failed to configure GSLB rul in the zone"); + } + } + + return true; + } + + private boolean checkGslbServiceEnabledInZone(long zoneId) { + + if (_gslbProvider == null) { + throw new CloudRuntimeException("No GSLB provider is available"); + } + + return _gslbProvider.isServiceEnabledInZone(zoneId); + } + + @Override + public GlobalLoadBalancerRule findById(long gslbRuleId) { + return _gslbRuleDao.findById(gslbRuleId); + } +} \ No newline at end of file diff --git a/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java b/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java new file mode 100755 index 00000000000..4338d65eff2 --- /dev/null +++ b/server/src/org/apache/cloudstack/region/gslb/GslbServiceProvider.java @@ -0,0 +1,36 @@ +/* + * 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.region.gslb; + +import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand; +import com.cloud.exception.ResourceUnavailableException; +import org.apache.cloudstack.region.RegionServiceProvider; + +public interface GslbServiceProvider extends RegionServiceProvider { + + public boolean isServiceEnabledInZone(long zoneId); + + public String getZoneGslbProviderPublicIp(long zoneId); + + public String getZoneGslbProviderPrivateIp(long zoneId); + + public boolean applyGlobalLoadBalancerRule(long zoneId, GlobalLoadBalancerConfigCommand gslbConfigCmd) + throws ResourceUnavailableException; + +} diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java new file mode 100644 index 00000000000..700fe8f7dde --- /dev/null +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -0,0 +1,974 @@ +// 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.region.gslb; + +import com.cloud.agent.AgentManager; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.dao.*; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.RulesManager; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.net.Ip; +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.cloudstack.api.command.user.region.ha.gslb.AssignToGlobalLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.region.ha.gslb.CreateGlobalLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.region.ha.gslb.DeleteGlobalLoadBalancerRuleCmd; +import org.apache.cloudstack.api.command.user.region.ha.gslb.RemoveFromGlobalLoadBalancerRuleCmd; +import org.apache.cloudstack.region.RegionVO; +import org.apache.cloudstack.region.dao.RegionDao; +import org.apache.log4j.Logger; +import org.junit.Test; +import org.mockito.Mockito; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.when; + +public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { + + private static final Logger s_logger = Logger.getLogger( GlobalLoadBalancingRulesServiceImplTest.class); + + @Test + public void testCreateGlobalLoadBalancerRule() throws Exception { + + s_logger.info("Running tests for CreateGlobalLoadBalancerRule() service API"); + + /* + * TEST 1: given valid parameters CreateGlobalLoadBalancerRule should succeed + */ + runCreateGlobalLoadBalancerRulePostiveTest(); + + /* + * TEST 2: given invalid algorithm CreateGlobalLoadBalancerRule should fail + */ + runCreateGlobalLoadBalancerRuleInvalidAlgorithm(); + + /* + * TEST 3: given invalid persistence method CreateGlobalLoadBalancerRule should fail + */ + runCreateGlobalLoadBalancerRuleInvalidStickyMethod(); + + /* + * TEST 4: given invalid service type CreateGlobalLoadBalancerRule should fail + */ + runCreateGlobalLoadBalancerRuleInvalidServiceType(); + + /* + * TEST 5: given 'domain name' that is already used by a different GSLB rule CreateGlobalLoadBalancerRule should fail + */ + runCreateGlobalLoadBalancerRuleInvalidDomainName(); + } + + @Test + public void testAssignToGlobalLoadBalancerRule() throws Exception { + + s_logger.info("Running tests for AssignToGlobalLoadBalancerRule() service API"); + + /* + * TEST 1: given valid gslb rule id, valid lb rule id, and caller has access to both the rules + * assignToGlobalLoadBalancerRule service API should succeed + */ + runAssignToGlobalLoadBalancerRuleTest(); + + /* + * TEST 2: given valid gslb rule id, two valid Lb rules but both belong to same zone then + * assignToGlobalLoadBalancerRule service API should fail + */ + runAssignToGlobalLoadBalancerRuleTestSameZoneLb(); + + /* + * TEST 3: if gslb rule is in revoke state assignToGlobalLoadBalancerRule service API should fail + */ + runAssignToGlobalLoadBalancerRuleTestRevokedState(); + } + + @Test + public void testRemoveFromGlobalLoadBalancerRule() throws Exception { + + s_logger.info("Running tests for RemoveFromGlobalLoadBalancerRule() service API"); + + /* + * TEST 1: given valid gslb rule id, valid lb rule id and is assigned to given gslb rule id + * then RemoveFromGlobalLoadBalancerRule service API should succeed + */ + runRemoveFromGlobalLoadBalancerRuleTest(); + + /* + * TEST 2: given valid gslb rule id, valid lb rule id but NOT assigned to given gslb rule id + * then RemoveFromGlobalLoadBalancerRule service API should fail + */ + runRemoveFromGlobalLoadBalancerRuleTestUnassignedLb(); + + /* + * TEST 3: given valid gslb rule id, INVALID lb rule id then RemoveFromGlobalLoadBalancerRule + * service API should fail + */ + runRemoveFromGlobalLoadBalancerRuleTestInvalidLb(); + } + + @Test + public void testDeleteGlobalLoadBalancerRule() throws Exception { + + s_logger.info("Running tests for DeleteGlobalLoadBalancerRule() service API"); + + /* + * TEST 1: given valid gslb rule id with assigned Lb rules, DeleteGlobalLoadBalancerRule() + * call should succeed, and Gslb rule should be set to revoke state + */ + runDeleteGlobalLoadBalancerRuleTestWithNoLbRules(); + + /* + * TEST 2: given valid gslb rule id with assigned Lb rules, DeleteGlobalLoadBalancerRule() + * call should succeed, and Gslb rule should be set to revoke state + */ + runDeleteGlobalLoadBalancerRuleTestWithLbRules(); + + + } + + void runCreateGlobalLoadBalancerRulePostiveTest() throws Exception { + + Transaction txn = Transaction.open("runCreateGlobalLoadBalancerRulePostiveTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + Account account = (Account) new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + when(gslbServiceImpl._gslbRuleDao.persist(any(GlobalLoadBalancerRuleVO.class))).thenReturn(new GlobalLoadBalancerRuleVO()); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + RegionVO region = new RegionVO(); + region.setGslbEnabled(true); + when(gslbServiceImpl._regionDao.findById(anyInt())).thenReturn(region); + + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + CreateGlobalLoadBalancerRuleCmd createCmd = new CreateGlobalLoadBalancerRuleCmdExtn(); + Class _class = createCmd.getClass().getSuperclass(); + + Field regionIdField = _class.getDeclaredField("regionId"); + regionIdField.setAccessible(true); + regionIdField.set(createCmd, new Integer(1)); + + Field algoField = _class.getDeclaredField("algorithm"); + algoField.setAccessible(true); + algoField.set(createCmd, "roundrobin"); + + Field stickyField = _class.getDeclaredField("stickyMethod"); + stickyField.setAccessible(true); + stickyField.set(createCmd, "sourceip"); + + Field nameField = _class.getDeclaredField("globalLoadBalancerRuleName"); + nameField.setAccessible(true); + nameField.set(createCmd, "gslb-rule"); + + Field descriptionField = _class.getDeclaredField("description"); + descriptionField.setAccessible(true); + descriptionField.set(createCmd, "testing create gslb-rule"); + + Field serviceDomainField = _class.getDeclaredField("serviceDomainName"); + serviceDomainField.setAccessible(true); + serviceDomainField.set(createCmd, "gslb-rule-domain"); + + Field serviceTypeField = _class.getDeclaredField("serviceType"); + serviceTypeField.setAccessible(true); + serviceTypeField.set(createCmd, "tcp"); + + try { + gslbServiceImpl.createGlobalLoadBalancerRule(createCmd); + } catch (Exception e) { + s_logger.info("exception in testing runCreateGlobalLoadBalancerRulePostiveTest message: " + e.toString()); + } + } + + void runCreateGlobalLoadBalancerRuleInvalidAlgorithm() throws Exception { + + Transaction txn = Transaction.open("runCreateGlobalLoadBalancerRulePostiveTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + Account account = (Account) new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + when(gslbServiceImpl._gslbRuleDao.persist(any(GlobalLoadBalancerRuleVO.class))).thenReturn(new GlobalLoadBalancerRuleVO()); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + RegionVO region = new RegionVO(); + region.setGslbEnabled(true); + when(gslbServiceImpl._regionDao.findById(anyInt())).thenReturn(region); + + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + CreateGlobalLoadBalancerRuleCmd createCmd = new CreateGlobalLoadBalancerRuleCmdExtn(); + Class _class = createCmd.getClass().getSuperclass(); + + Field regionIdField = _class.getDeclaredField("regionId"); + regionIdField.setAccessible(true); + regionIdField.set(createCmd, new Integer(1)); + + Field algoField = _class.getDeclaredField("algorithm"); + algoField.setAccessible(true); + algoField.set(createCmd, "invalidalgo"); + + Field stickyField = _class.getDeclaredField("stickyMethod"); + stickyField.setAccessible(true); + stickyField.set(createCmd, "sourceip"); + + Field nameField = _class.getDeclaredField("globalLoadBalancerRuleName"); + nameField.setAccessible(true); + nameField.set(createCmd, "gslb-rule"); + + Field descriptionField = _class.getDeclaredField("description"); + descriptionField.setAccessible(true); + descriptionField.set(createCmd, "testing create gslb-rule"); + + Field serviceDomainField = _class.getDeclaredField("serviceDomainName"); + serviceDomainField.setAccessible(true); + serviceDomainField.set(createCmd, "gslb-rule-domain"); + + Field serviceTypeField = _class.getDeclaredField("serviceType"); + serviceTypeField.setAccessible(true); + serviceTypeField.set(createCmd, "tcp"); + + try { + gslbServiceImpl.createGlobalLoadBalancerRule(createCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("Invalid Algorithm")); + } + } + + void runCreateGlobalLoadBalancerRuleInvalidStickyMethod() throws Exception { + + Transaction txn = Transaction.open("runCreateGlobalLoadBalancerRulePostiveTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + Account account = (Account) new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + when(gslbServiceImpl._gslbRuleDao.persist(any(GlobalLoadBalancerRuleVO.class))).thenReturn(new GlobalLoadBalancerRuleVO()); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + RegionVO region = new RegionVO(); + region.setGslbEnabled(true); + when(gslbServiceImpl._regionDao.findById(anyInt())).thenReturn(region); + + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + CreateGlobalLoadBalancerRuleCmd createCmd = new CreateGlobalLoadBalancerRuleCmdExtn(); + Class _class = createCmd.getClass().getSuperclass(); + + Field regionIdField = _class.getDeclaredField("regionId"); + regionIdField.setAccessible(true); + regionIdField.set(createCmd, new Integer(1)); + + Field algoField = _class.getDeclaredField("algorithm"); + algoField.setAccessible(true); + algoField.set(createCmd, "roundrobin"); + + Field stickyField = _class.getDeclaredField("stickyMethod"); + stickyField.setAccessible(true); + stickyField.set(createCmd, "ivalidstickymethod"); + + Field nameField = _class.getDeclaredField("globalLoadBalancerRuleName"); + nameField.setAccessible(true); + nameField.set(createCmd, "gslb-rule"); + + Field descriptionField = _class.getDeclaredField("description"); + descriptionField.setAccessible(true); + descriptionField.set(createCmd, "testing create gslb-rule"); + + Field serviceDomainField = _class.getDeclaredField("serviceDomainName"); + serviceDomainField.setAccessible(true); + serviceDomainField.set(createCmd, "gslb-rule-domain"); + + Field serviceTypeField = _class.getDeclaredField("serviceType"); + serviceTypeField.setAccessible(true); + serviceTypeField.set(createCmd, "tcp"); + + try { + gslbServiceImpl.createGlobalLoadBalancerRule(createCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("Invalid persistence")); + } + } + + void runCreateGlobalLoadBalancerRuleInvalidServiceType() throws Exception { + + Transaction txn = Transaction.open("runCreateGlobalLoadBalancerRulePostiveTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + Account account = (Account) new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + when(gslbServiceImpl._gslbRuleDao.persist(any(GlobalLoadBalancerRuleVO.class))).thenReturn(new GlobalLoadBalancerRuleVO()); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + RegionVO region = new RegionVO(); + region.setGslbEnabled(true); + when(gslbServiceImpl._regionDao.findById(anyInt())).thenReturn(region); + + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + CreateGlobalLoadBalancerRuleCmd createCmd = new CreateGlobalLoadBalancerRuleCmdExtn(); + Class _class = createCmd.getClass().getSuperclass(); + + Field regionIdField = _class.getDeclaredField("regionId"); + regionIdField.setAccessible(true); + regionIdField.set(createCmd, new Integer(1)); + + Field algoField = _class.getDeclaredField("algorithm"); + algoField.setAccessible(true); + algoField.set(createCmd, "roundrobin"); + + Field stickyField = _class.getDeclaredField("stickyMethod"); + stickyField.setAccessible(true); + stickyField.set(createCmd, "sourceip"); + + Field nameField = _class.getDeclaredField("globalLoadBalancerRuleName"); + nameField.setAccessible(true); + nameField.set(createCmd, "gslb-rule"); + + Field descriptionField = _class.getDeclaredField("description"); + descriptionField.setAccessible(true); + descriptionField.set(createCmd, "testing create gslb-rule"); + + Field serviceDomainField = _class.getDeclaredField("serviceDomainName"); + serviceDomainField.setAccessible(true); + serviceDomainField.set(createCmd, "gslb-rule-domain"); + + Field serviceTypeField = _class.getDeclaredField("serviceType"); + serviceTypeField.setAccessible(true); + serviceTypeField.set(createCmd, "invalidtcp"); + + try { + gslbServiceImpl.createGlobalLoadBalancerRule(createCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("Invalid service type")); + } + } + + void runCreateGlobalLoadBalancerRuleInvalidDomainName() throws Exception { + + Transaction txn = Transaction.open("runCreateGlobalLoadBalancerRulePostiveTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + Account account = (Account) new AccountVO("testaccount", 1, + "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + RegionVO region = new RegionVO(); + region.setGslbEnabled(true); + when(gslbServiceImpl._regionDao.findById(anyInt())).thenReturn(region); + + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + CreateGlobalLoadBalancerRuleCmd createCmd = new CreateGlobalLoadBalancerRuleCmdExtn(); + Class _class = createCmd.getClass().getSuperclass(); + + Field regionIdField = _class.getDeclaredField("regionId"); + regionIdField.setAccessible(true); + regionIdField.set(createCmd, new Integer(1)); + + Field algoField = _class.getDeclaredField("algorithm"); + algoField.setAccessible(true); + algoField.set(createCmd, "roundrobin"); + + Field stickyField = _class.getDeclaredField("stickyMethod"); + stickyField.setAccessible(true); + stickyField.set(createCmd, "sourceip"); + + Field nameField = _class.getDeclaredField("globalLoadBalancerRuleName"); + nameField.setAccessible(true); + nameField.set(createCmd, "gslb-rule"); + + Field descriptionField = _class.getDeclaredField("description"); + descriptionField.setAccessible(true); + descriptionField.set(createCmd, "testing create gslb-rule"); + + Field serviceDomainField = _class.getDeclaredField("serviceDomainName"); + serviceDomainField.setAccessible(true); + serviceDomainField.set(createCmd, "gslb-rule-domain"); + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO(); + when(gslbServiceImpl._gslbRuleDao.findByDomainName("gslb-rule-domain")).thenReturn(gslbRule); + + Field serviceTypeField = _class.getDeclaredField("serviceType"); + serviceTypeField.setAccessible(true); + serviceTypeField.set(createCmd, "tcp"); + + try { + gslbServiceImpl.createGlobalLoadBalancerRule(createCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("Domain name " + "gslb-rule-domain" + "is in use")); + } + } + + void runAssignToGlobalLoadBalancerRuleTest() throws Exception { + + Transaction txn = Transaction.open("runAssignToGlobalLoadBalancerRuleTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + AssignToGlobalLoadBalancerRuleCmd assignCmd = new AssignToGlobalLoadBalancerRuleCmdExtn(); + Class _class = assignCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(assignCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + LoadBalancerVO lbRule = new LoadBalancerVO(); + lbRule.setState(FirewallRule.State.Active); + Field networkIdField = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField.setAccessible(true); + networkIdField.set(lbRule, new Long(1)); + Field sourceIpAddressId = LoadBalancerVO.class.getSuperclass().getDeclaredField("sourceIpAddressId"); + sourceIpAddressId.setAccessible(true); + sourceIpAddressId.set(lbRule, new Long(1)); + + when(gslbServiceImpl._lbDao.findById(new Long(1))).thenReturn(lbRule); + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRules.set(assignCmd, lbRuleIds); + + NetworkVO networkVo = new NetworkVO(); + Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); + dcID.setAccessible(true); + dcID.set(networkVo, new Long(1)); + when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); + + IPAddressVO ip = new IPAddressVO(new Ip("10.1.1.1"), 1, 1,1 ,true); + when(gslbServiceImpl._ipAddressDao.findById(new Long(1))).thenReturn(ip); + + try { + gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); + } catch (Exception e) { + s_logger.info("exception in testing runAssignToGlobalLoadBalancerRuleTest message: " + e.toString()); + } + } + + void runAssignToGlobalLoadBalancerRuleTestSameZoneLb() throws Exception { + + Transaction txn = Transaction.open("runAssignToGlobalLoadBalancerRuleTestSameZoneLb"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + AssignToGlobalLoadBalancerRuleCmd assignCmd = new AssignToGlobalLoadBalancerRuleCmdExtn(); + Class _class = assignCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 3, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(assignCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 3, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + LoadBalancerVO lbRule1 = new LoadBalancerVO(); + lbRule1.setState(FirewallRule.State.Active); + Field networkIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField1.setAccessible(true); + networkIdField1.set(lbRule1, new Long(1)); + Field idField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); + idField1.setAccessible(true); + idField1.set(lbRule1, new Long(1)); + + LoadBalancerVO lbRule2 = new LoadBalancerVO(); + lbRule2.setState(FirewallRule.State.Active); + Field networkIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField2.setAccessible(true); + networkIdField2.set(lbRule2, new Long(1)); + Field idField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); + idField2.setAccessible(true); + idField2.set(lbRule2, new Long(2)); + + when(gslbServiceImpl._lbDao.findById(new Long(1))).thenReturn(lbRule1); + when(gslbServiceImpl._lbDao.findById(new Long(2))).thenReturn(lbRule2); + + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRuleIds.add(new Long(2)); + lbRules.set(assignCmd, lbRuleIds); + + NetworkVO networkVo = new NetworkVO(); + Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); + dcID.setAccessible(true); + dcID.set(networkVo, new Long(1)); + when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); + + try { + gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("Load balancer rule specified should be in unique zone")); + } + } + + void runAssignToGlobalLoadBalancerRuleTestRevokedState() throws Exception { + + Transaction txn = Transaction.open("runAssignToGlobalLoadBalancerRuleTestRevokedState"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + AssignToGlobalLoadBalancerRuleCmd assignCmd = new AssignToGlobalLoadBalancerRuleCmdExtn(); + Class _class = assignCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(assignCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Revoke); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + LoadBalancerVO lbRule = new LoadBalancerVO(); + lbRule.setState(FirewallRule.State.Active); + Field networkIdField = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField.setAccessible(true); + networkIdField.set(lbRule, new Long(1)); + + when(gslbServiceImpl._lbDao.findById(new Long(1))).thenReturn(lbRule); + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRules.set(assignCmd, lbRuleIds); + + NetworkVO networkVo = new NetworkVO(); + Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); + dcID.setAccessible(true); + dcID.set(networkVo, new Long(1)); + when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); + + try { + gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("revoked state")); + } + } + + void runRemoveFromGlobalLoadBalancerRuleTest() throws Exception { + + Transaction txn = Transaction.open("runRemoveFromGlobalLoadBalancerRuleTest"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + gslbServiceImpl._gslbProvider = Mockito.mock(GslbServiceProvider.class); + + RemoveFromGlobalLoadBalancerRuleCmd removeFromGslbCmd = new RemoveFromGlobalLoadBalancerRuleCmdExtn(); + Class _class = removeFromGslbCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(removeFromGslbCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + LoadBalancerVO lbRule = new LoadBalancerVO(); + lbRule.setState(FirewallRule.State.Active); + Field networkIdField = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField.setAccessible(true); + networkIdField.set(lbRule, new Long(1)); + Field idField = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); + idField.setAccessible(true); + idField.set(lbRule, new Long(1)); + Field sourceIpAddressId = LoadBalancerVO.class.getSuperclass().getDeclaredField("sourceIpAddressId"); + sourceIpAddressId.setAccessible(true); + sourceIpAddressId.set(lbRule, new Long(1)); + + when(gslbServiceImpl._lbDao.findById(new Long(1))).thenReturn(lbRule); + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRules.set(removeFromGslbCmd, lbRuleIds); + + NetworkVO networkVo = new NetworkVO(); + Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); + dcID.setAccessible(true); + dcID.set(networkVo, new Long(1)); + when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); + + GlobalLoadBalancerLbRuleMapVO gslbLbMap = new GlobalLoadBalancerLbRuleMapVO(1, 1); + List listSslbLbMap = new ArrayList(); + listSslbLbMap.add(gslbLbMap); + when(gslbServiceImpl._gslbLbMapDao.listByGslbRuleId(new Long(1))).thenReturn(listSslbLbMap); + + when(gslbServiceImpl._gslbLbMapDao.findByGslbRuleIdAndLbRuleId(new Long(1), new Long(1))).thenReturn(gslbLbMap); + + IPAddressVO ip = new IPAddressVO(new Ip("10.1.1.1"), 1, 1,1 ,true); + when(gslbServiceImpl._ipAddressDao.findById(new Long(1))).thenReturn(ip); + + gslbServiceImpl.removeFromGlobalLoadBalancerRule(removeFromGslbCmd); + } + + void runRemoveFromGlobalLoadBalancerRuleTestUnassignedLb() throws Exception { + + Transaction txn = Transaction.open("runRemoveFromGlobalLoadBalancerRuleTestUnassignedLb"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + RemoveFromGlobalLoadBalancerRuleCmd removeFromGslbCmd = new RemoveFromGlobalLoadBalancerRuleCmdExtn(); + Class _class = removeFromGslbCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(removeFromGslbCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + LoadBalancerVO lbRule = new LoadBalancerVO(); + lbRule.setState(FirewallRule.State.Active); + Field networkIdField = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + networkIdField.setAccessible(true); + networkIdField.set(lbRule, new Long(1)); + Field idField = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); + idField.setAccessible(true); + idField.set(lbRule, new Long(1)); + + when(gslbServiceImpl._lbDao.findById(new Long(1))).thenReturn(lbRule); + + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRules.set(removeFromGslbCmd, lbRuleIds); + + NetworkVO networkVo = new NetworkVO(); + Field dcID = NetworkVO.class.getDeclaredField("dataCenterId"); + dcID.setAccessible(true); + dcID.set(networkVo, new Long(1)); + when(gslbServiceImpl._networkDao.findById(new Long(1))).thenReturn(networkVo); + + try { + gslbServiceImpl.removeFromGlobalLoadBalancerRule(removeFromGslbCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("not assigned to global load balancer rule")); + } + } + + void runRemoveFromGlobalLoadBalancerRuleTestInvalidLb() throws Exception { + + Transaction txn = Transaction.open("runRemoveFromGlobalLoadBalancerRuleTestInvalidLb"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + RemoveFromGlobalLoadBalancerRuleCmd removeFromGslbCmd = new RemoveFromGlobalLoadBalancerRuleCmdExtn(); + Class _class = removeFromGslbCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(removeFromGslbCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + Field lbRules = _class.getDeclaredField("loadBalancerRulesIds"); + lbRules.setAccessible(true); + List lbRuleIds = new ArrayList(); + lbRuleIds.add(new Long(1)); + lbRules.set(removeFromGslbCmd, lbRuleIds); + + try { + gslbServiceImpl.removeFromGlobalLoadBalancerRule(removeFromGslbCmd); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains("load balancer rule ID does not exist")); + } + } + + void runDeleteGlobalLoadBalancerRuleTestWithNoLbRules() throws Exception { + + Transaction txn = Transaction.open("runDeleteGlobalLoadBalancerRuleTestWithNoLbRules"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + DeleteGlobalLoadBalancerRuleCmd deleteCmd = new DeleteGlobalLoadBalancerRuleCmdExtn(); + Class _class = deleteCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(deleteCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + GlobalLoadBalancerLbRuleMapVO gslbLbMap = new GlobalLoadBalancerLbRuleMapVO(); + gslbLbMap.setGslbLoadBalancerId(1); + gslbLbMap.setLoadBalancerId(1); + List gslbLbMapList = new ArrayList(); + gslbLbMapList.add(gslbLbMap); + when(gslbServiceImpl._gslbLbMapDao.listByGslbRuleId(new Long(1))).thenReturn(gslbLbMapList); + + try { + gslbServiceImpl.deleteGlobalLoadBalancerRule(deleteCmd); + Assert.assertTrue(gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke); + } catch (Exception e) { + s_logger.info("exception in testing runDeleteGlobalLoadBalancerRuleTestWithNoLbRules. " + e.toString()); + } + } + + void runDeleteGlobalLoadBalancerRuleTestWithLbRules() throws Exception { + + Transaction txn = Transaction.open("runDeleteGlobalLoadBalancerRuleTestWithLbRules"); + + GlobalLoadBalancingRulesServiceImpl gslbServiceImpl = new GlobalLoadBalancingRulesServiceImpl(); + + gslbServiceImpl._accountMgr = Mockito.mock(AccountManager.class); + gslbServiceImpl._gslbRuleDao = Mockito.mock(GlobalLoadBalancerRuleDao.class); + gslbServiceImpl._gslbLbMapDao = Mockito.mock(GlobalLoadBalancerLbRuleMapDao.class); + gslbServiceImpl._regionDao = Mockito.mock(RegionDao.class); + gslbServiceImpl._rulesMgr = Mockito.mock(RulesManager.class); + gslbServiceImpl._lbDao = Mockito.mock(LoadBalancerDao.class); + gslbServiceImpl._networkDao = Mockito.mock(NetworkDao.class); + gslbServiceImpl._globalConfigDao = Mockito.mock(ConfigurationDao.class); + gslbServiceImpl._ipAddressDao = Mockito.mock(IPAddressDao.class); + gslbServiceImpl._agentMgr = Mockito.mock(AgentManager.class); + + DeleteGlobalLoadBalancerRuleCmd deleteCmd = new DeleteGlobalLoadBalancerRuleCmdExtn(); + Class _class = deleteCmd.getClass().getSuperclass(); + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(gslbServiceImpl._accountMgr.getAccount(anyLong())).thenReturn(account); + + UserContext.registerContext(1, account, null, true); + + Field gslbRuleId = _class.getDeclaredField("id"); + gslbRuleId.setAccessible(true); + gslbRuleId.set(deleteCmd, new Long(1)); + + GlobalLoadBalancerRuleVO gslbRule = new GlobalLoadBalancerRuleVO("test-gslb-rule", "test-gslb-rule", + "test-domain", "roundrobin", "sourceip", "tcp", 1, 1, 1, GlobalLoadBalancerRule.State.Active); + when(gslbServiceImpl._gslbRuleDao.findById(new Long(1))).thenReturn(gslbRule); + + + GlobalLoadBalancerLbRuleMapVO gslbLmMap = new GlobalLoadBalancerLbRuleMapVO(1,1); + List gslbLbMapVos = new ArrayList(); + gslbLbMapVos.add(gslbLmMap); + when(gslbServiceImpl._gslbLbMapDao.listByGslbRuleId(new Long(1))).thenReturn(gslbLbMapVos); + + try { + gslbServiceImpl.deleteGlobalLoadBalancerRule(deleteCmd); + Assert.assertTrue(gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke); + Assert.assertTrue(gslbLmMap.isRevoke() == true); + } catch (Exception e) { + s_logger.info("exception in testing runDeleteGlobalLoadBalancerRuleTestWithLbRules. " + e.toString()); + } + } + + public class CreateGlobalLoadBalancerRuleCmdExtn extends CreateGlobalLoadBalancerRuleCmd { + public long getEntityOwnerId() { + return 1; + } + } + + public class AssignToGlobalLoadBalancerRuleCmdExtn extends AssignToGlobalLoadBalancerRuleCmd { + public long getEntityOwnerId() { + return 1; + } + } + + public class RemoveFromGlobalLoadBalancerRuleCmdExtn extends RemoveFromGlobalLoadBalancerRuleCmd { + public long getEntityOwnerId() { + return 1; + } + } + + public class DeleteGlobalLoadBalancerRuleCmdExtn extends DeleteGlobalLoadBalancerRuleCmd { + public long getEntityOwnerId() { + return 1; + } + } +} diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index eb650cc9da1..9eed0a65e2f 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -201,3 +201,41 @@ CREATE VIEW `cloud`.`event_view` AS `cloud`.`projects` ON projects.project_account_id = event.account_id left join `cloud`.`event` eve ON event.start_id = eve.id; + + +ALTER TABLE `cloud`.`region` ADD COLUMN `gslb_service_enabled` tinyint(1) unsigned NOT NULL DEFAULT 1 COMMENT 'Is GSLB service enalbed in the Region'; + +ALTER TABLE `cloud`.`external_load_balancer_devices` ADD COLUMN `is_gslb_provider` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if load balancer appliance is acting as gslb service provider in the zone'; + +ALTER TABLE `cloud`.`external_load_balancer_devices` ADD COLUMN `gslb_site_publicip` varchar(255) DEFAULT NULL COMMENT 'GSLB service Provider site public ip'; + +ALTER TABLE `cloud`.`external_load_balancer_devices` ADD COLUMN `gslb_site_privateip` varchar(255) DEFAULT NULL COMMENT 'GSLB service Provider site private ip'; + +CREATE TABLE `cloud`.`global_load_balancing_rules` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `uuid` varchar(40), + `account_id` bigint unsigned NOT NULL COMMENT 'account id', + `domain_id` bigint unsigned NOT NULL COMMENT 'domain id', + `region_id` int unsigned NOT NULL, + `name` varchar(255) NOT NULL, + `description` varchar(4096) NULL COMMENT 'description', + `state` char(32) NOT NULL COMMENT 'current state of this rule', + `algorithm` varchar(255) NOT NULL COMMENT 'load balancing algorithm used to distribbute traffic across zones', + `persistence` varchar(255) NOT NULL COMMENT 'session persistence used across the zone', + `service_type` varchar(255) NOT NULL COMMENT 'GSLB service type (tcp/udp)', + `gslb_domain_name` varchar(255) NOT NULL COMMENT 'DNS name for the GSLB service that is used to provide a FQDN for the GSLB service', + PRIMARY KEY (`id`), + CONSTRAINT `fk_global_load_balancing_rules_account_id` FOREIGN KEY (`account_id`) REFERENCES `account`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_global_load_balancing_rules_region_id` FOREIGN KEY(`region_id`) REFERENCES `region`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`global_load_balancer_lb_rule_map` ( + `id` bigint unsigned NOT NULL auto_increment, + `gslb_rule_id` bigint unsigned NOT NULL, + `lb_rule_id` bigint unsigned NOT NULL, + `revoke` tinyint(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 is when rule is set for Revoke', + PRIMARY KEY (`id`), + UNIQUE KEY (`gslb_rule_id`, `lb_rule_id`), + CONSTRAINT `fk_gslb_rule_id` FOREIGN KEY(`gslb_rule_id`) REFERENCES `global_load_balancing_rules`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_lb_rule_id` FOREIGN KEY(`lb_rule_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8;