diff --git a/core/src/com/cloud/network/resource/NetscalerResource.java b/core/src/com/cloud/network/resource/NetscalerResource.java index 8bbbc3c746d..1667b949910 100644 --- a/core/src/com/cloud/network/resource/NetscalerResource.java +++ b/core/src/com/cloud/network/resource/NetscalerResource.java @@ -89,7 +89,7 @@ public class NetscalerResource implements ServerResource { private String _objectNamePathSep = "-"; nitro_service _netscalerService ; - Long timeout = new Long(100000); + Long _timeout = new Long(100000); base_response apiCallResult; public NetscalerResource () { @@ -157,10 +157,12 @@ public class NetscalerResource implements ServerResource { _inline = Boolean.parseBoolean((String) params.get("inline")); + // validate device configration parameters login(); - enableNetScalerLoadBalancing(); + checkLoadBalancingFeatureEnabled(); validateInterfaces(_publicInterface, _privateInterface); validateDeviceType(_deviceName); + return true; } catch (Exception e) { throw new ConfigurationException(e.getMessage()); @@ -170,26 +172,34 @@ public class NetscalerResource implements ServerResource { private void login() throws ExecutionException { try { _netscalerService = new nitro_service(_ip, "https"); - apiCallResult = _netscalerService.login(_username, _password, timeout); + _netscalerService.set_credential(_username, _password); + _netscalerService.set_timeout(_timeout); + apiCallResult = _netscalerService.login(); if (apiCallResult.errorcode != 0) { - throw new ExecutionException ("Failed to log in to Netscaler device at " + _ip + " due to error " + apiCallResult.errorcode + " and message " + apiCallResult.message); + throw new ExecutionException ("Failed to log in to Netscaler device at " + _ip + " due to error " + apiCallResult.errorcode + " and message " + apiCallResult.message); } } catch (nitro_exception e) { - throw new ExecutionException("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); + throw new ExecutionException("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); } catch (Exception e) { - throw new ExecutionException("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); + throw new ExecutionException("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); } } - private void enableNetScalerLoadBalancing() throws ExecutionException { + private void checkLoadBalancingFeatureEnabled() throws ExecutionException { try { - String[] feature = new String[1]; - feature[0] = "LB"; - _netscalerService.enable_features(feature); + String[] features = _netscalerService.get_enabled_features(); + if (features != null) { + for (String feature : features) { + if (feature.equalsIgnoreCase("LB")) { + return; + } + } + } + throw new ExecutionException("Load balancing feature is not enabled on the device. Please enable the load balancing feature and add the device."); } catch (nitro_exception e) { - throw new ExecutionException("Enabling netscaler load balancing feature failed due to error " + apiCallResult.errorcode + " and message " + e.getMessage()); + throw new ExecutionException("Failed to verify load balancing is enalbed due to error " + apiCallResult.errorcode + " and message " + e.getMessage()); } catch (Exception e) { - throw new ExecutionException("Enabling netscaler load balancing feature failed due to " + e.getMessage()); + throw new ExecutionException("Failed to verify load balancing is enalbed due to " + e.getMessage()); } } @@ -291,32 +301,16 @@ public class NetscalerResource implements ServerResource { return Answer.createUnsupportedCommandAnswer(cmd); } - String lbProtocol; - String lbMethod; LoadBalancerTO[] loadBalancers = cmd.getLoadBalancers(); - + if (loadBalancers == null) { + return new Answer(cmd); + } + for (LoadBalancerTO loadBalancer : loadBalancers) { - - if (loadBalancer.getProtocol() == null) { - lbProtocol = "TCP"; - } else if (loadBalancer.getProtocol().equals(NetUtils.TCP_PROTO)){ - lbProtocol = "TCP"; - } else if (loadBalancer.getProtocol().equals(NetUtils.UDP_PROTO)) { - lbProtocol = "UDP"; - } else { - throw new ExecutionException("Got invalid protocol: " + loadBalancer.getProtocol()); - } - - if (loadBalancer.getAlgorithm().equals("roundrobin")) { - lbMethod = "ROUNDROBIN"; - } else if (loadBalancer.getAlgorithm().equals("leastconn")) { - lbMethod = "LEASTCONNECTION"; - } else { - throw new ExecutionException("Got invalid load balancing algorithm: " + loadBalancer.getAlgorithm()); - } - String srcIp = loadBalancer.getSrcIp(); - int srcPort = loadBalancer.getSrcPort(); + int srcPort = loadBalancer.getSrcPort(); + String lbProtocol = loadBalancer.getProtocol(); + String lbAlgorithm = loadBalancer.getAlgorithm(); String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort, lbProtocol); boolean destinationsToAdd = false; @@ -330,7 +324,7 @@ public class NetscalerResource implements ServerResource { if (!loadBalancer.isRevoked() && destinationsToAdd) { // create a load balancing virtual server - addLBVirtualServer(nsVirtualServerName, srcIp, srcPort, lbMethod, lbProtocol); + addLBVirtualServer(nsVirtualServerName, srcIp, srcPort, lbAlgorithm, lbProtocol); if (s_logger.isDebugEnabled()) { s_logger.debug("Created load balancing virtual server " + nsVirtualServerName + " on the Netscaler device"); } @@ -391,13 +385,13 @@ public class NetscalerResource implements ServerResource { // delete the binding apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(_netscalerService, binding); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to delete the binding between the virtual server: " + nsVirtualServerName + " and service:" + nsServiceName); + throw new ExecutionException("Failed to delete the binding between the virtual server: " + nsVirtualServerName + " and service:" + nsServiceName + " due to" + apiCallResult.message); } // delete the service apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, nsServiceName); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to delete service: " + nsServiceName); + throw new ExecutionException("Failed to delete service: " + nsServiceName + " due to " + apiCallResult.message); } // delete the server if there is no associated services @@ -405,7 +399,7 @@ public class NetscalerResource implements ServerResource { if ((services == null) || (services.length == 0)) { apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to remove server:" + nsServerName); + throw new ExecutionException("Failed to remove server:" + nsServerName + " due to " + apiCallResult.message); } } } @@ -414,8 +408,8 @@ public class NetscalerResource implements ServerResource { } } } else { - // delete the deployed load balancing rule and its destinations - lbvserver lbserver = lbvserver.get(_netscalerService, nsVirtualServerName); + // delete the implemented load balancing rule and its destinations + lbvserver lbserver = getVirtualServerIfExisits(nsVirtualServerName); if (lbserver == null) { throw new ExecutionException("Failed to find virtual server with name:" + nsVirtualServerName); } @@ -427,7 +421,7 @@ public class NetscalerResource implements ServerResource { String serviceName = binding.get_servicename(); apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(_netscalerService, binding); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to unbind servic from the lb virtual server: " + nsVirtualServerName); + throw new ExecutionException("Failed to unbind service from the lb virtual server: " + nsVirtualServerName + " due to " + apiCallResult.message); } com.citrix.netscaler.nitro.resource.config.basic.service svc = com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName); @@ -441,7 +435,7 @@ public class NetscalerResource implements ServerResource { if ((services == null) || (services.length == 0)) { apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to remove server:" + nsServerName); + throw new ExecutionException("Failed to remove server:" + nsServerName + " due to " + apiCallResult.message); } } } @@ -455,7 +449,7 @@ public class NetscalerResource implements ServerResource { } saveConfiguration(); - return new Answer(cmd); + return new Answer(cmd); } catch (ExecutionException e) { s_logger.error("Failed to execute LoadBalancerConfigCommand due to " + e.getMessage()); if (shouldRetry(numRetries)) { @@ -494,10 +488,7 @@ public class NetscalerResource implements ServerResource { } private void addGuestVlanAndSubnet(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { - org.apache.axis.types.UnsignedInt result; - try { - String vlanName = generateVlanName(vlanTag); if (!nsVlanExists(vlanTag)) { // add new vlan vlan vlanObj = new vlan(); @@ -542,13 +533,11 @@ public class NetscalerResource implements ServerResource { } catch (nitro_exception e) { throw new ExecutionException("Failed to implement guest network on the Netscaler device"); } catch (Exception e) { - throw new ExecutionException("Failed to implement guest network on the Netscaler device"); + throw new ExecutionException("Failed to implement guest network on the Netscaler device"); } } private void deleteGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { - org.apache.axis.types.UnsignedInt result; - try { if (nsVlanExists(vlanTag)) { @@ -624,6 +613,20 @@ public class NetscalerResource implements ServerResource { } } + private lbvserver getVirtualServerIfExisits(String lbVServerName ) throws ExecutionException { + try { + return lbvserver.get(_netscalerService, lbVServerName); + } catch (nitro_exception e) { + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return null; + } else { + throw new ExecutionException(e.getMessage()); + } + } catch (Exception e) { + throw new ExecutionException(e.getMessage()); + } + } + private boolean nsServiceExists(String serviceName) throws ExecutionException { try { if (com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName) != null) { @@ -698,19 +701,53 @@ public class NetscalerResource implements ServerResource { private void addLBVirtualServer(String virtualServerName, String srcIp, int srcPort, String lbMethod, String lbProtocol) throws ExecutionException { try { - lbvserver vserver = new lbvserver(); + + if (lbProtocol == null) { + lbProtocol = "TCP"; + } else if (lbProtocol.equals(NetUtils.TCP_PROTO)){ + lbProtocol = "TCP"; + } else if (lbProtocol.equals(NetUtils.UDP_PROTO)) { + lbProtocol = "UDP"; + } else { + throw new ExecutionException("Got invalid protocol: " + lbProtocol); + } + + if (lbMethod.equals("roundrobin")) { + lbMethod = "ROUNDROBIN"; + } else if (lbMethod.equals("leastconn")) { + lbMethod = "LEASTCONNECTION"; + } else { + throw new ExecutionException("Got invalid load balancing algorithm: " + lbMethod); + } + + boolean vserverExisis = false; + lbvserver vserver = getVirtualServerIfExisits(virtualServerName); + if (vserver == null) { + vserver = new lbvserver(); + } else { + vserverExisis = true; + } vserver.set_name(virtualServerName); vserver.set_ipv46(srcIp); vserver.set_port(srcPort); vserver.set_servicetype(lbProtocol); vserver.set_lbmethod(lbMethod); - apiCallResult = lbvserver.add(_netscalerService,vserver); + + if (vserverExisis) { + apiCallResult = lbvserver.update(_netscalerService,vserver); + } else { + apiCallResult = lbvserver.add(_netscalerService,vserver); + } if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to create new virtual server:" + virtualServerName); + throw new ExecutionException("Failed to create new virtual server:" + virtualServerName+ " due to " + apiCallResult.message); } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created load balancing virtual server " + virtualServerName + " on the Netscaler device"); + } } catch (nitro_exception e) { if (e.getErrorCode() != NitroError.NS_RESOURCE_EXISTS) { - throw new ExecutionException("Failed to create new virtual server:" + virtualServerName + " due to " + e.getMessage()); + throw new ExecutionException("Failed to create new virtual server:" + virtualServerName + " due to " + e.getMessage()); } } catch (Exception e) { throw new ExecutionException("Failed to create new virtual server:" + virtualServerName + " due to " + e.getMessage()); @@ -725,10 +762,14 @@ public class NetscalerResource implements ServerResource { } apiCallResult = lbvserver.delete(_netscalerService, vserver); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Failed to remove virtual server:" + virtualServerName); + throw new ExecutionException("Failed to remove virtual server:" + virtualServerName + " due to " + apiCallResult.message); } } catch (nitro_exception e) { - throw new ExecutionException("Failed to remove virtual server:" + virtualServerName +" due to " + e.getMessage()); + if (e.getErrorCode() == NitroError.NS_RESOURCE_NOT_EXISTS) { + return; + } else { + throw new ExecutionException("Failed remove virtual server:" + virtualServerName +" due to " + e.getMessage()); + } } catch (Exception e) { throw new ExecutionException("Failed to remove virtual server:" + virtualServerName +" due to " + e.getMessage()); } @@ -738,7 +779,7 @@ public class NetscalerResource implements ServerResource { try { apiCallResult = nsconfig.save(_netscalerService); if (apiCallResult.errorcode != 0) { - throw new ExecutionException("Error occured while saving configuration changes to Netscaler device due to error:" + apiCallResult.errorcode); + throw new ExecutionException("Error occured while saving configuration changes to Netscaler device due to " + apiCallResult.message); } } catch (nitro_exception e) { throw new ExecutionException("Failed to save configuration changes to Netscaler device due to " + e.getMessage()); @@ -751,25 +792,25 @@ public class NetscalerResource implements ServerResource { ExternalNetworkResourceUsageAnswer answer = new ExternalNetworkResourceUsageAnswer(cmd); try { - - lbvserver_stats[] stats = lbvserver_stats.get(_netscalerService); + + lbvserver_stats[] stats = lbvserver_stats.get(_netscalerService); - for (lbvserver_stats stat_entry : stats) { - String lbvserverName = stat_entry.get_name(); - lbvserver vserver = lbvserver.get(_netscalerService, lbvserverName); - String lbVirtualServerIp = vserver.get_ipv46(); + for (lbvserver_stats stat_entry : stats) { + String lbvserverName = stat_entry.get_name(); + lbvserver vserver = lbvserver.get(_netscalerService, lbvserverName); + String lbVirtualServerIp = vserver.get_ipv46(); - long[] bytesSentAndReceived = answer.ipBytes.get(lbVirtualServerIp); - if (bytesSentAndReceived == null) { - bytesSentAndReceived = new long[]{0, 0}; - } - bytesSentAndReceived[0] += stat_entry.get_totalrequestbytes(); - bytesSentAndReceived[1] += stat_entry.get_totalresponsebytes(); + long[] bytesSentAndReceived = answer.ipBytes.get(lbVirtualServerIp); + if (bytesSentAndReceived == null) { + bytesSentAndReceived = new long[]{0, 0}; + } + bytesSentAndReceived[0] += stat_entry.get_totalrequestbytes(); + bytesSentAndReceived[1] += stat_entry.get_totalresponsebytes(); - if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) { - answer.ipBytes.put(lbVirtualServerIp, bytesSentAndReceived); - } - } + if (bytesSentAndReceived[0] >= 0 && bytesSentAndReceived[1] >= 0) { + answer.ipBytes.put(lbVirtualServerIp, bytesSentAndReceived); + } + } } catch (Exception e) { s_logger.error(e); throw new ExecutionException(e.getMessage()); @@ -785,20 +826,16 @@ public class NetscalerResource implements ServerResource { } private boolean shouldRetry(int numRetries) { - try { - if (numRetries > 0) { - login(); - return true; - } + try { + if (numRetries > 0) { + login(); + return true; + } } catch (Exception e) { - s_logger.error("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); + s_logger.error("Failed to log in to Netscaler device at " + _ip + " due to " + e.getMessage()); } return false; } - - private String generateVlanName(long vlanTag) { - return genObjectName("cloud-vlan", String.valueOf(vlanTag)); - } private String generateNSVirtualServerName(String srcIp, long srcPort, String protocol) { return genObjectName("cloud-VirtualServer", protocol, srcIp, srcPort); diff --git a/deps/cloud-netscaler.jar b/deps/cloud-netscaler.jar old mode 100644 new mode 100755 index 8c1bf8d3fc6..a073b5067c8 Binary files a/deps/cloud-netscaler.jar and b/deps/cloud-netscaler.jar differ diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index cfa666ac40d..bfbb278d9c3 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -322,7 +322,10 @@ public enum Config { ProjectSMTPPassword("Project Defaults", ManagementServer.class, String.class, "project.smtp.password", null, "Password for SMTP authentication (applies only if project.smtp.useAuth is true)", null), ProjectSMTPPort("Project Defaults", ManagementServer.class, Integer.class, "project.smtp.port", "465", "Port the SMTP server is listening on", null), ProjectSMTPUseAuth("Project Defaults", ManagementServer.class, String.class, "project.smtp.useAuth", null, "If true, use SMTP authentication when sending emails", null), - ProjectSMTPUsername("Project Defaults", ManagementServer.class, String.class, "project.smtp.username", null, "Username for SMTP authentication (applies only if project.smtp.useAuth is true)", null); + ProjectSMTPUsername("Project Defaults", ManagementServer.class, String.class, "project.smtp.username", null, "Username for SMTP authentication (applies only if project.smtp.useAuth is true)", null), + + DefaultExternalLoadBalancerCapacity("Advanced", ManagementServer.class, String.class, "external.lb.default.capacity", "50", "default number of networks permitted per external load balancer device", null), + DefaultExternalFirewallCapacity("Advanced", ManagementServer.class, String.class, "external.firewall.default.capacity", "50", "default number of networks permitted per external load firewall device", null); private final String _category; private final Class _componentClass; diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index 1681d9e9368..b76a91718e2 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -214,9 +214,7 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl ExternalFirewallDeviceVO fwDevice = new ExternalFirewallDeviceVO(externalFirewall.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName, capacity, dedicatedUse); - if (capacity != 0) { - fwDevice.setState(FirewallDeviceState.Enabled); - } + _externalFirewallDeviceDao.persist(fwDevice); DetailVO hostDetail = new DetailVO(externalFirewall.getId(), ApiConstants.FIREWALL_DEVICE_ID, String.valueOf(fwDevice.getId())); diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceVO.java b/server/src/com/cloud/network/ExternalFirewallDeviceVO.java index b43d6b2189b..2d98e0618ef 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceVO.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceVO.java @@ -56,9 +56,9 @@ public class ExternalFirewallDeviceVO { @Column(name = "device_name") private String deviceName; - @Column(name="state") + @Column(name="device_state") @Enumerated(value=EnumType.STRING) - FirewallDeviceState state; + FirewallDeviceState deviceState; @Column(name="is_dedicated") private boolean isDedicatedDevice; @@ -86,10 +86,11 @@ public class ExternalFirewallDeviceVO { this.providerName = provider_name; this.deviceName = device_name; this.hostId = hostId; - this.state = FirewallDeviceState.Disabled; + this.deviceState = FirewallDeviceState.Disabled; this.allocationState = FirewallDeviceAllocationState.Free; this.capacity = capacity; this.isDedicatedDevice = dedicated; + this.deviceState = FirewallDeviceState.Enabled; this.uuid = UUID.randomUUID().toString(); } @@ -125,12 +126,12 @@ public class ExternalFirewallDeviceVO { this.capacity = capacity; } - public FirewallDeviceState getState() { - return state; + public FirewallDeviceState getDeviceState() { + return deviceState; } - public void setState(FirewallDeviceState state) { - this.state = state; + public void setDeviceState(FirewallDeviceState state) { + this.deviceState = state; } public FirewallDeviceAllocationState getAllocationState() { diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java index 8523386630f..9ce5d38aa56 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManager.java @@ -35,6 +35,9 @@ import com.cloud.utils.component.Manager; public interface ExternalLoadBalancerDeviceManager extends Manager{ + + public static final int DEFAULT_LOAD_BALANCER_CAPACITY = 50; + /** * adds a load balancer device in to a physical network * @param physicalNetworkId physical network id of the network in to which device to be added diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index 30abc8023a9..52a1882312f 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -122,35 +122,62 @@ import com.cloud.vm.dao.NicDao; public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase implements ExternalLoadBalancerDeviceManager, ResourceStateAdapter { - @Inject NetworkExternalLoadBalancerDao _networkExternalLBDao; - @Inject ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao; - @Inject HostDao _hostDao; - @Inject DataCenterDao _dcDao; - @Inject HostDetailsDao _detailsDao; - @Inject NetworkManager _networkMgr; - @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; - @Inject NicDao _nicDao; - @Inject AgentManager _agentMgr; - @Inject ResourceManager _resourceMgr; - @Inject IPAddressDao _ipAddressDao; - @Inject VlanDao _vlanDao; - @Inject NetworkOfferingDao _networkOfferingDao; - @Inject AccountDao _accountDao; - @Inject PhysicalNetworkDao _physicalNetworkDao; - @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; - @Inject AccountManager _accountMgr; - @Inject UserStatisticsDao _userStatsDao; - @Inject NetworkDao _networkDao; - @Inject DomainRouterDao _routerDao; - @Inject LoadBalancerDao _loadBalancerDao; - @Inject PortForwardingRulesDao _portForwardingRulesDao; - @Inject ConfigurationDao _configDao; - @Inject HostDetailsDao _hostDetailDao; - @Inject NetworkExternalLoadBalancerDao _networkLBDao; - @Inject NetworkServiceMapDao _ntwkSrvcProviderDao; + @Inject + NetworkExternalLoadBalancerDao _networkExternalLBDao; + @Inject + ExternalLoadBalancerDeviceDao _externalLoadBalancerDeviceDao; + @Inject + HostDao _hostDao; + @Inject + DataCenterDao _dcDao; + @Inject + HostDetailsDao _detailsDao; + @Inject + NetworkManager _networkMgr; + @Inject + InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; + @Inject + NicDao _nicDao; + @Inject + AgentManager _agentMgr; + @Inject + ResourceManager _resourceMgr; + @Inject + IPAddressDao _ipAddressDao; + @Inject + VlanDao _vlanDao; + @Inject + NetworkOfferingDao _networkOfferingDao; + @Inject + AccountDao _accountDao; + @Inject + PhysicalNetworkDao _physicalNetworkDao; + @Inject + PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; + @Inject + AccountManager _accountMgr; + @Inject + UserStatisticsDao _userStatsDao; + @Inject + NetworkDao _networkDao; + @Inject + DomainRouterDao _routerDao; + @Inject + LoadBalancerDao _loadBalancerDao; + @Inject + PortForwardingRulesDao _portForwardingRulesDao; + @Inject + ConfigurationDao _configDao; + @Inject + HostDetailsDao _hostDetailDao; + @Inject + NetworkExternalLoadBalancerDao _networkLBDao; + @Inject + NetworkServiceMapDao _ntwkSrvcProviderDao; ScheduledExecutorService _executor; - int _externalNetworkStatsInterval; + private int _externalNetworkStatsInterval; + private long _defaultLbCapacity; private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalLoadBalancerDeviceManagerImpl.class); @Override @@ -222,9 +249,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase ExternalLoadBalancerDeviceVO lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName, capacity, dedicatedUse, inline); - if (capacity != 0) { - lbDeviceVO.setState(LBDeviceState.Enabled); - } + _externalLoadBalancerDeviceDao.persist(lbDeviceVO); DetailVO hostDetail = new DetailVO(host.getId(), ApiConstants.LOAD_BALANCER_DEVICE_ID, String.valueOf(lbDeviceVO.getId())); @@ -322,20 +347,12 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase if (dedicatedLb) { lbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); if (lbDevices != null && !lbDevices.isEmpty()) { - - //return first device that is free, fully configured and meant for dedicated use + // return first device that is free, fully configured and meant for dedicated use for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { if (lbdevice.getState() == LBDeviceState.Enabled && lbdevice.getIsDedicatedDevice()) { return lbdevice; } } - - //if there are no dedicated lb device then return first device that is free, fully configured - for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { - if (lbdevice.getState() == LBDeviceState.Enabled) { - return lbdevice; - } - } } } else { // get the LB devices that are already allocated for shared use @@ -354,33 +371,36 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase continue; } - // skip if the device is intended to be used in dedicated mode only - if (lbdevice.getIsDedicatedDevice()) { - continue; - } - + // get the used capacity from the list of guest networks that are mapped to this load balancer List mappedNetworks = _networkExternalLBDao.listByLoadBalancerDeviceId(lbdevice.getId()); - // get the list of guest networks that are mapped to this load balancer long usedCapacity = ((mappedNetworks == null) || (mappedNetworks.isEmpty()))? 0 : mappedNetworks.size(); - // get max number of guest networks that can be mapped to this device + + // get the configured capacity for this device long fullCapacity = lbdevice.getCapacity(); + if (fullCapacity == 0) { + fullCapacity = _defaultLbCapacity; // if capacity not configured then use the default + } long freeCapacity = fullCapacity - usedCapacity; if (freeCapacity > 0) { if (maxFreeCapacityLbdevice == null) { maxFreeCapacityLbdevice = lbdevice; maxFreeCapacity = freeCapacity; - } - if (freeCapacity > maxFreeCapacity) { + } else if (freeCapacity > maxFreeCapacity) { maxFreeCapacityLbdevice = lbdevice; maxFreeCapacity = freeCapacity; } } } + + // return the device with maximum free capacity and is meant for shared use + if (maxFreeCapacityLbdevice != null) { + return maxFreeCapacityLbdevice; + } } - // if we are here then there are no existing LB devices in shared use or the devices in shared use has no free capacity - // so allocate a new one from the pool of free LB devices + // if we are here then there are no existing LB devices in shared use or the devices in shared use has no free capacity left + // so allocate a new load balancer configured for shared use from the pool of free LB devices lbDevices = _externalLoadBalancerDeviceDao.listByProviderAndDeviceAllocationState(physicalNetworkId, provider, LBDeviceAllocationState.Free); if (lbDevices != null && !lbDevices.isEmpty()) { for (ExternalLoadBalancerDeviceVO lbdevice : lbDevices) { @@ -391,6 +411,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase } } + // there are no devices which capcity throw new InsufficientNetworkCapacityException("Unable to find a load balancing provider with sufficient capcity " + " to implement the network", Network.class, network.getId()); } @@ -614,9 +635,9 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase // FIXME: should the device allocation be done during network implement phase or do a lazy allocation // when first rule for the network is configured?? - // find a load balancer device as per the network offering boolean dedicatedLB = offering.getDedicatedLB(); try { + // find a load balancer device for this network as per the network offering ExternalLoadBalancerDeviceVO lbDevice = findSuitableLoadBalancerForNetwork(guestConfig, dedicatedLB); lbDeviceId = lbDevice.getId(); @@ -763,6 +784,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("ExternalNetworkMonitor")); } + _defaultLbCapacity = NumbersUtil.parseLong(_configDao.getValue(Config.DefaultExternalLoadBalancerCapacity.key()), 50); _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); return true; } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java index 8d2e498855a..69a7ade7876 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java @@ -57,7 +57,7 @@ public class ExternalLoadBalancerDeviceVO { @Column(name = "device_name") private String deviceName; - @Column(name="state") + @Column(name="device_state") @Enumerated(value=EnumType.STRING) private LBDeviceState state; @@ -105,6 +105,7 @@ public class ExternalLoadBalancerDeviceVO { this.isDedicatedDevice = dedicated; this.isInlineMode = inline; this.isManagedDevice = false; + this.state = LBDeviceState.Enabled; this.uuid = UUID.randomUUID().toString(); if (device_name.equalsIgnoreCase(ExternalNetworkDeviceManager.NetworkDevice.NetscalerSDXLoadBalancer.getName())) { diff --git a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java index 7e048105805..359bd917005 100644 --- a/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java +++ b/server/src/com/cloud/network/dao/ExternalFirewallDeviceDaoImpl.java @@ -55,7 +55,7 @@ public class ExternalFirewallDeviceDaoImpl extends GenericDaoBase networks = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId); if ((networks != null) && !networks.isEmpty()) { - if (capacity < networks.size()) { + if (capacity != null && capacity < networks.size()) { throw new CloudRuntimeException("There are more number of networks already using this netscaler device than configured capacity"); } @@ -265,8 +263,12 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe } } - if (capacity != null) { - lbDeviceVo.setCapacity(capacity); + if (!NetworkDevice.NetscalerSDXLoadBalancer.getName().equalsIgnoreCase(deviceName)) { + if (capacity != null) { + lbDeviceVo.setCapacity(capacity); + } + } else { + // FIXME how to interpret configured capacity of the SDX device } if(dedicatedUse != null) { @@ -284,9 +286,9 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe Transaction txn = Transaction.currentTxn(); txn.start(); - lbDeviceVo.setState(LBDeviceState.Enabled); _lbDeviceDao.update(lbDeviceId, lbDeviceVo); + // FIXME get the row lock to avoid race condition _detailsDao.persist(lbDeviceVo.getHostId(), lbDetails); HostVO host = _hostDao.findById(lbDeviceVo.getHostId()); txn.commit(); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 817dfe95254..04ab1d2afec 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1948,13 +1948,13 @@ CREATE TABLE `cloud`.`external_load_balancer_devices` ( `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this load balancer device', `device_name` varchar(255) NOT NULL COMMENT 'name of the load balancer device', `capacity` bigint unsigned NOT NULL DEFAULT 0 COMMENT 'Capacity of the load balancer device', - `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', + `device_state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state (Free/Shared/Dedicated/Provider) of the device', - `is_dedicated` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance meant for dedicated use only', - `is_inline` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if netscaler load balancer to be used in in-line configuration with firewall', - `is_managed` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance is provisioned and its life cycle is managed by by cloudstack', + `is_dedicated` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance is provisioned for dedicated use only', + `is_inline` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if load balancer will be used in in-line configuration with firewall', + `is_managed` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if load balancer appliance is provisioned and its life cycle is managed by by cloudstack', `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external load balancer device', - `parent_host_id` bigint unsigned COMMENT 'if the device/appliance is cloudstack managed, then host id on which this device/appliance is provisioned', + `parent_host_id` bigint unsigned COMMENT 'if the load balancer appliance is cloudstack managed, then host id on which this appliance is provisioned', PRIMARY KEY (`id`), CONSTRAINT `fk_external_lb_devices_host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, CONSTRAINT `fk_external_lb_devices_parent_host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, @@ -1967,7 +1967,7 @@ CREATE TABLE `cloud`.`external_firewall_devices` ( `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which firewall device is added', `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this firewall device', `device_name` varchar(255) NOT NULL COMMENT 'name of the firewall device', - `state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', + `device_state` varchar(32) NOT NULL DEFAULT 'Disabled' COMMENT 'state (enabled/disabled/shutdown) of the device', `is_dedicated` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 if device/appliance meant for dedicated use only', `allocation_state` varchar(32) NOT NULL DEFAULT 'Free' COMMENT 'Allocation state (Free/Allocated) of the device', `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external firewall device',