diff --git a/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java b/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java index ee70a88a618..dc1cc0454ef 100644 --- a/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java +++ b/api/src/com/cloud/api/response/NetscalerLoadBalancerResponse.java @@ -43,9 +43,21 @@ public class NetscalerLoadBalancerResponse extends BaseResponse { @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_CAPACITY) @Param(description="device capacity") private Long deviceCapacity; - @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED) @Param(description="device capacity") + @SerializedName(ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED) @Param(description="true if device is dedicated for an account") private Boolean dedicatedLoadBalancer; + @SerializedName(ApiConstants.INLINE) @Param(description="true if device is inline with firewall device") + private Boolean inlineLoadBalancer; + + @SerializedName(ApiConstants.PUBLIC_INTERFACE) @Param(description="the public interface of the load balancer") + private String publicInterface; + + @SerializedName(ApiConstants.PRIVATE_INTERFACE) @Param(description="the private interface of the load balancer") + private String privateInterface; + + @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the management IP address of the external load balancer") + private String ipAddress; + public void setId(long lbDeviceId) { this.id.setValue(lbDeviceId); } @@ -69,7 +81,24 @@ public class NetscalerLoadBalancerResponse extends BaseResponse { public void setDedicatedLoadBalancer(boolean isDedicated) { this.dedicatedLoadBalancer = isDedicated; } + public void setDeviceState(String deviceState) { this.deviceState = deviceState; } + + public void setInlineMode(boolean inline) { + this.inlineLoadBalancer = inline; + } + + public void setPublicInterface(String publicInterface) { + this.publicInterface = publicInterface; + } + + public void setPrivateInterface(String privateInterface) { + this.privateInterface = privateInterface; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } } diff --git a/core/src/com/cloud/network/resource/NetscalerResource.java b/core/src/com/cloud/network/resource/NetscalerResource.java index f7a337735da..8bbbc3c746d 100644 --- a/core/src/com/cloud/network/resource/NetscalerResource.java +++ b/core/src/com/cloud/network/resource/NetscalerResource.java @@ -72,6 +72,7 @@ public class NetscalerResource implements ServerResource { // deployment configuration private String _name; private String _zoneId; + private String _physicalNetworkId; private String _ip; private String _username; private String _password; @@ -81,12 +82,13 @@ public class NetscalerResource implements ServerResource { private String _guid; private boolean _inline; private boolean _isSdx; + private String _deviceName; private static final Logger s_logger = Logger.getLogger(NetscalerResource.class); protected Gson _gson; private String _objectNamePathSep = "-"; - nitro_service nsService ; + nitro_service _netscalerService ; Long timeout = new Long(100000); base_response apiCallResult; @@ -99,48 +101,57 @@ public class NetscalerResource implements ServerResource { try { _name = (String) params.get("name"); if (_name == null) { - throw new ConfigurationException("Unable to find name"); + throw new ConfigurationException("Unable to find name in the configuration parameters"); } _zoneId = (String) params.get("zoneId"); if (_zoneId == null) { - throw new ConfigurationException("Unable to find zone"); + throw new ConfigurationException("Unable to find zone Id in the configuration parameters"); + } + + _physicalNetworkId = (String) params.get("physicalNetworkId"); + if (_physicalNetworkId == null) { + throw new ConfigurationException("Unable to find physical network id in the configuration parameters"); } _ip = (String) params.get("ip"); if (_ip == null) { - throw new ConfigurationException("Unable to find IP"); + throw new ConfigurationException("Unable to find IP address in the configuration parameters"); } _username = (String) params.get("username"); if (_username == null) { - throw new ConfigurationException("Unable to find username"); + throw new ConfigurationException("Unable to find username in the configuration parameters"); } _password = (String) params.get("password"); if (_password == null) { - throw new ConfigurationException("Unable to find password"); + throw new ConfigurationException("Unable to find password in the configuration parameters"); } _publicInterface = (String) params.get("publicinterface"); if (_publicInterface == null) { - throw new ConfigurationException("Unable to find public interface"); + throw new ConfigurationException("Unable to find public interface in the configuration parameters"); } _privateInterface = (String) params.get("privateinterface"); if (_privateInterface == null) { - throw new ConfigurationException("Unable to find private interface"); + throw new ConfigurationException("Unable to find private interface in the configuration parameters"); } _numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 2); _guid = (String)params.get("guid"); if (_guid == null) { - throw new ConfigurationException("Unable to find the guid"); + throw new ConfigurationException("Unable to find the guid in the configuration parameters"); } - String deviceName = (String) params.get("deviceName"); - if (deviceName.equalsIgnoreCase("NetscalerSDXLoadBalancer")) { + _deviceName = (String) params.get("deviceName"); + if (_deviceName == null) { + throw new ConfigurationException("Unable to find the device name in the configuration parameters"); + } + + if (_deviceName.equalsIgnoreCase("NetscalerSDXLoadBalancer")) { _isSdx = true; } @@ -148,7 +159,8 @@ public class NetscalerResource implements ServerResource { login(); enableNetScalerLoadBalancing(); - + validateInterfaces(_publicInterface, _privateInterface); + validateDeviceType(_deviceName); return true; } catch (Exception e) { throw new ConfigurationException(e.getMessage()); @@ -157,8 +169,8 @@ public class NetscalerResource implements ServerResource { private void login() throws ExecutionException { try { - nsService = new nitro_service(_ip); //FIXME: use nitro_service(_ip, "https"). secure calls are unreliable with Nitro API on MPX 9.3 nitro_service(_ip, "https") - apiCallResult = nsService.login(_username, _password, timeout); + _netscalerService = new nitro_service(_ip, "https"); + apiCallResult = _netscalerService.login(_username, _password, timeout); 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); } @@ -173,7 +185,7 @@ public class NetscalerResource implements ServerResource { try { String[] feature = new String[1]; feature[0] = "LB"; - nsService.enable_features(feature); + _netscalerService.enable_features(feature); } catch (nitro_exception e) { throw new ExecutionException("Enabling netscaler load balancing feature failed due to error " + apiCallResult.errorcode + " and message " + e.getMessage()); } catch (Exception e) { @@ -181,6 +193,14 @@ public class NetscalerResource implements ServerResource { } } + private void validateInterfaces(String publicInterface, String privateInterface) throws ExecutionException { + //FIXME verify the device type (VPX, MPX, SDX) specified indeed matches with actual device type + } + + private void validateDeviceType(String deviceType) throws ExecutionException { + //FIXME validate public and private interface strings as well + } + @Override public StartupCommand[] initialize() { StartupExternalLoadBalancerCommand cmd = new StartupExternalLoadBalancerCommand(); @@ -328,7 +348,7 @@ public class NetscalerResource implements ServerResource { com.citrix.netscaler.nitro.resource.config.basic.server nsServer = new com.citrix.netscaler.nitro.resource.config.basic.server(); nsServer.set_name(nsServerName); nsServer.set_ipaddress(destination.getDestIp()); - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.add(nsService, nsServer); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.add(_netscalerService, nsServer); if ((apiCallResult.errorcode != 0) && (apiCallResult.errorcode != NitroError.NS_RESOURCE_EXISTS)) { throw new ExecutionException("Failed to add server " + destination.getDestIp() + " due to" + apiCallResult.message); } @@ -342,7 +362,7 @@ public class NetscalerResource implements ServerResource { newService.set_servername(nsServerName); newService.set_state("ENABLED"); newService.set_servicetype(lbProtocol); - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.add(nsService, newService); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.add(_netscalerService, newService); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to create service " + nsServiceName + " using server " + nsServerName + " due to" + apiCallResult.message); } @@ -353,7 +373,7 @@ public class NetscalerResource implements ServerResource { com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding svcBinding = new com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding(); svcBinding.set_name(nsVirtualServerName); svcBinding.set_servicename(nsServiceName); - apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.add(nsService, svcBinding); + apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.add(_netscalerService, svcBinding); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to bind service: " + nsServiceName + " to the lb virtual server: " + nsVirtualServerName + " on Netscaler device"); @@ -364,26 +384,26 @@ public class NetscalerResource implements ServerResource { } } else { // remove a destination from the deployed load balancing rule - com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, nsVirtualServerName); + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, nsVirtualServerName); if (serviceBindings != null) { for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { if (nsServiceName.equalsIgnoreCase(binding.get_servicename())) { // delete the binding - apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(nsService, 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); } // delete the service - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, nsServiceName); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, nsServiceName); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to delete service: " + nsServiceName); } // delete the server if there is no associated services - server_service_binding[] services = server_service_binding.get(nsService, nsServerName); + server_service_binding[] services = server_service_binding.get(_netscalerService, nsServerName); if ((services == null) || (services.length == 0)) { - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, nsServerName); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove server:" + nsServerName); } @@ -395,31 +415,31 @@ public class NetscalerResource implements ServerResource { } } else { // delete the deployed load balancing rule and its destinations - lbvserver lbserver = lbvserver.get(nsService, nsVirtualServerName); + lbvserver lbserver = lbvserver.get(_netscalerService, nsVirtualServerName); if (lbserver == null) { throw new ExecutionException("Failed to find virtual server with name:" + nsVirtualServerName); } //unbind the all services associated with this virtual server - com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, nsVirtualServerName); + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, nsVirtualServerName); if (serviceBindings != null) { for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { String serviceName = binding.get_servicename(); - apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(nsService, binding); + 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); } - com.citrix.netscaler.nitro.resource.config.basic.service svc = com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService, serviceName); + com.citrix.netscaler.nitro.resource.config.basic.service svc = com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName); String nsServerName = svc.get_servername(); // delete the service - com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, serviceName); + com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, serviceName); //delete the server if no more services attached - server_service_binding[] services = server_service_binding.get(nsService, nsServerName); + server_service_binding[] services = server_service_binding.get(_netscalerService, nsServerName); if ((services == null) || (services.length == 0)) { - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, nsServerName); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove server:" + nsServerName); } @@ -482,7 +502,7 @@ public class NetscalerResource implements ServerResource { // add new vlan vlan vlanObj = new vlan(); vlanObj.set_id(vlanTag); - apiCallResult = vlan.add(nsService, vlanObj); + apiCallResult = vlan.add(_netscalerService, vlanObj); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to add new vlan with tag:" + vlanTag + "due to" + apiCallResult.message); } @@ -492,7 +512,7 @@ public class NetscalerResource implements ServerResource { selfIp.set_ipaddress(vlanSelfIp); selfIp.set_netmask(vlanNetmask); selfIp.set_type("SNIP"); - apiCallResult = nsip.add(nsService, selfIp); + apiCallResult = nsip.add(_netscalerService, selfIp); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to add new self-ip due to "+ apiCallResult.message); } @@ -502,7 +522,7 @@ public class NetscalerResource implements ServerResource { ipVlanBinding.set_id(vlanTag); ipVlanBinding.set_ipaddress(vlanSelfIp); ipVlanBinding.set_netmask(vlanNetmask); - apiCallResult = vlan_nsip_binding.add(nsService, ipVlanBinding); + apiCallResult = vlan_nsip_binding.add(_netscalerService, ipVlanBinding); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to bind vlan with tag:" + vlanTag + " to the subnet due to" + apiCallResult.message); } @@ -512,7 +532,7 @@ public class NetscalerResource implements ServerResource { vlanBinding.set_ifnum(_privateInterface); vlanBinding.set_tagged(true); vlanBinding.set_id(vlanTag); - apiCallResult = vlan_interface_binding.add(nsService, vlanBinding); + apiCallResult = vlan_interface_binding.add(_netscalerService, vlanBinding); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to bind vlan with tag:" + vlanTag + " with the interface " + _privateInterface + " due to " + apiCallResult.message); } @@ -540,7 +560,7 @@ public class NetscalerResource implements ServerResource { vlanIfBinding.set_id(vlanTag); vlanIfBinding.set_ifnum(_privateInterface); vlanIfBinding.set_tagged(true); - apiCallResult = vlan_interface_binding.delete(nsService, vlanIfBinding); + apiCallResult = vlan_interface_binding.delete(_netscalerService, vlanIfBinding); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to unbind vlan:" + vlanTag + " with the private interface due to " + apiCallResult.message); } @@ -550,20 +570,20 @@ public class NetscalerResource implements ServerResource { vlanSnipBinding.set_netmask(vlanNetmask); vlanSnipBinding.set_ipaddress(vlanSelfIp); vlanSnipBinding.set_id(vlanTag); - apiCallResult = vlan_nsip_binding.delete(nsService, vlanSnipBinding); + apiCallResult = vlan_nsip_binding.delete(_netscalerService, vlanSnipBinding); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to unbind vlan:" + vlanTag + " with the subnet due to " + apiCallResult.message); } // remove subnet IP - nsip subnetIp = nsip.get(nsService, vlanSelfIp); - apiCallResult = nsip.delete(nsService, subnetIp); + nsip subnetIp = nsip.get(_netscalerService, vlanSelfIp); + apiCallResult = nsip.delete(_netscalerService, subnetIp); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove subnet ip:" + vlanTag + " to the subnet due to" + apiCallResult.message); } // remove vlan - apiCallResult = com.citrix.netscaler.nitro.resource.config.network.vlan.delete(nsService, vlanTag); + apiCallResult = com.citrix.netscaler.nitro.resource.config.network.vlan.delete(_netscalerService, vlanTag); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove vlan with tag:" + vlanTag + "due to" + apiCallResult.message); } @@ -577,7 +597,7 @@ public class NetscalerResource implements ServerResource { private boolean nsVlanExists(long vlanTag) { try { - if (vlan.get(nsService, new Long(vlanTag)) != null) { + if (vlan.get(_netscalerService, new Long(vlanTag)) != null) { return true; } return false; @@ -588,7 +608,7 @@ public class NetscalerResource implements ServerResource { private boolean nsServerExists(String serverName) throws ExecutionException { try { - if (com.citrix.netscaler.nitro.resource.config.basic.server.get(nsService, serverName) != null) { + if (com.citrix.netscaler.nitro.resource.config.basic.server.get(_netscalerService, serverName) != null) { return true; } else { return false; @@ -606,7 +626,7 @@ public class NetscalerResource implements ServerResource { private boolean nsServiceExists(String serviceName) throws ExecutionException { try { - if (com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService, serviceName) != null) { + if (com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName) != null) { return true; } else { return false; @@ -624,7 +644,7 @@ public class NetscalerResource implements ServerResource { private boolean nsServiceBindingExists(String lbVirtualServer, String serviceName) throws ExecutionException { try { - com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(nsService, lbVirtualServer); + com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, lbVirtualServer); if (serviceBindings != null) { for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) { if (serviceName.equalsIgnoreCase(binding.get_servicename())) { @@ -642,7 +662,7 @@ public class NetscalerResource implements ServerResource { private void deleteServersInGuestVlan(long vlanTag, String vlanSelfIp, String vlanNetmask) throws ExecutionException { try { - com.citrix.netscaler.nitro.resource.config.basic.server[] serverList = com.citrix.netscaler.nitro.resource.config.basic.server.get(nsService); + com.citrix.netscaler.nitro.resource.config.basic.server[] serverList = com.citrix.netscaler.nitro.resource.config.basic.server.get(_netscalerService); if (serverList == null) { return; @@ -653,11 +673,11 @@ public class NetscalerResource implements ServerResource { // check if server belong to same subnet as one associated with vlan if (NetUtils.sameSubnet(vlanSelfIp, server.get_ipaddress(), vlanNetmask)) { // first remove services associated with this server - com.citrix.netscaler.nitro.resource.config.basic.service serveicesList[] = com.citrix.netscaler.nitro.resource.config.basic.service.get(nsService); + com.citrix.netscaler.nitro.resource.config.basic.service serveicesList[] = com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService); if (serveicesList != null) { for (com.citrix.netscaler.nitro.resource.config.basic.service svc : serveicesList) { if (svc.get_servername().equals(server.get_ipaddress())) { - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(nsService, svc.get_name()); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, svc.get_name()); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove service:" + svc.get_name()); } @@ -665,7 +685,7 @@ public class NetscalerResource implements ServerResource { } } // remove the server - apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(nsService, server.get_name()); + apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, server.get_name()); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove server:" + server.get_name()); } @@ -684,7 +704,7 @@ public class NetscalerResource implements ServerResource { vserver.set_port(srcPort); vserver.set_servicetype(lbProtocol); vserver.set_lbmethod(lbMethod); - apiCallResult = lbvserver.add(nsService,vserver); + apiCallResult = lbvserver.add(_netscalerService,vserver); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to create new virtual server:" + virtualServerName); } @@ -699,11 +719,11 @@ public class NetscalerResource implements ServerResource { private void removeLBVirtualServer (String virtualServerName) throws ExecutionException { try { - lbvserver vserver = lbvserver.get(nsService, virtualServerName); + lbvserver vserver = lbvserver.get(_netscalerService, virtualServerName); if (vserver == null) { throw new ExecutionException("Failed to find virtual server with name:" + virtualServerName); } - apiCallResult = lbvserver.delete(nsService, vserver); + apiCallResult = lbvserver.delete(_netscalerService, vserver); if (apiCallResult.errorcode != 0) { throw new ExecutionException("Failed to remove virtual server:" + virtualServerName); } @@ -716,7 +736,7 @@ public class NetscalerResource implements ServerResource { private void saveConfiguration() throws ExecutionException { try { - apiCallResult = nsconfig.save(nsService); + 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); } @@ -732,11 +752,11 @@ public class NetscalerResource implements ServerResource { try { - lbvserver_stats[] stats = lbvserver_stats.get(nsService); + lbvserver_stats[] stats = lbvserver_stats.get(_netscalerService); for (lbvserver_stats stat_entry : stats) { String lbvserverName = stat_entry.get_name(); - lbvserver vserver = lbvserver.get(nsService, lbvserverName); + lbvserver vserver = lbvserver.get(_netscalerService, lbvserverName); String lbVirtualServerIp = vserver.get_ipv46(); long[] bytesSentAndReceived = answer.ipBytes.get(lbVirtualServerIp); diff --git a/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java b/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java index 722a10c7765..2b4d962628d 100644 --- a/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java +++ b/server/src/com/cloud/api/commands/ConfigureNetscalerLoadBalancerCmd.java @@ -58,9 +58,12 @@ public class ConfigureNetscalerLoadBalancerCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_CAPACITY, type=CommandType.LONG, required=false, description="capacity of the device, Capacity will be interpreted as number of networks device can handle") private Long capacity; - @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED, type=CommandType.BOOLEAN, required=false, description="true if this netscaler device to dedicated for a account") + @Parameter(name=ApiConstants.LOAD_BALANCER_DEVICE_DEDICATED, type=CommandType.BOOLEAN, required=false, description="true if this netscaler device to dedicated for a account, false if the netscaler device will be shared by multiple accounts") private Boolean dedicatedUse; + @Parameter (name=ApiConstants.INLINE, type=CommandType.BOOLEAN, required=false, description="true if netscaler load balancer is intended to be used in in-line with firewall, false if netscaler load balancer will side-by-side with firewall") + private Boolean inline; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -77,6 +80,10 @@ public class ConfigureNetscalerLoadBalancerCmd extends BaseAsyncCmd { return dedicatedUse; } + public Boolean getLoadBalancerInline() { + return inline; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index 029575f2864..97d7ea12c85 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -160,6 +160,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase String guid; PhysicalNetworkVO pNetwork=null; NetworkDevice ntwkDevice = NetworkDevice.getNetworkDevice(deviceName); + Transaction txn = null; long zoneId; if ((ntwkDevice == null) || (url == null) || (username == null) || (resource == null) || (password == null) ) { @@ -192,7 +193,8 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase String ipAddress = uri.getHost(); Map hostDetails = new HashMap(); - guid = getExternalNetworkResourceGuid(pNetwork.getId(), deviceName, ipAddress); + guid = getExternalLoadBalancerResourceGuid(pNetwork.getId(), deviceName, ipAddress); + hostDetails.put("name", guid); hostDetails.put("guid", guid); hostDetails.put("zoneId", String.valueOf(pNetwork.getDataCenterId())); hostDetails.put("ip", ipAddress); @@ -202,19 +204,27 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase hostDetails.put("deviceName", deviceName); // leave parameter validation to be part server resource configure - Map params = new HashMap(); - UrlUtil.parseQueryParameters(uri.getQuery(), false, params); - hostDetails.putAll(params); + Map configParams = new HashMap(); + UrlUtil.parseQueryParameters(uri.getQuery(), false, configParams); + hostDetails.putAll(configParams); try { resource.configure(guid, hostDetails); Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalLoadBalancer, hostDetails); if (host != null) { - Transaction txn = Transaction.currentTxn(); + txn = Transaction.currentTxn(); txn.start(); - ExternalLoadBalancerDeviceVO lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkSvcProvider.getProviderName(), deviceName); + boolean dedicatedUse = (configParams.get("lbdevicededicated") != null) ? Boolean.parseBoolean(configParams.get("lbdevicededicated")) : false; + boolean inline = (configParams.get("lbdeviceinline") != null) ? Boolean.parseBoolean(configParams.get("lbdeviceinline")) : false; + long capacity = NumbersUtil.parseLong((String)configParams.get("lbdevicecapacity"), 0); + + 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())); @@ -298,7 +308,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase return response; } - public String getExternalNetworkResourceGuid(long physicalNetworkId, String deviceName, String ip) { + public String getExternalLoadBalancerResourceGuid(long physicalNetworkId, String deviceName, String ip) { return physicalNetworkId + "-" + deviceName + "-" + ip; } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java index 1bf9cdb9d19..8d2e498855a 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceVO.java @@ -67,7 +67,10 @@ public class ExternalLoadBalancerDeviceVO { @Column(name="is_managed") private boolean isManagedDevice; - + + @Column(name="is_inline") + private boolean isInlineMode; + @Column(name="is_dedicated") private boolean isDedicatedDevice; @@ -90,13 +93,17 @@ public class ExternalLoadBalancerDeviceVO { Provider // This state is set only for device that can dynamically provision LB appliances } - public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name) { + public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, + long capacity, boolean dedicated, boolean inline) { this.physicalNetworkId = physicalNetworkId; this.providerName = provider_name; this.deviceName = device_name; this.hostId = hostId; this.state = LBDeviceState.Disabled; this.allocationState = LBDeviceAllocationState.Free; + this.capacity = capacity; + this.isDedicatedDevice = dedicated; + this.isInlineMode = inline; this.isManagedDevice = false; this.uuid = UUID.randomUUID().toString(); @@ -105,8 +112,9 @@ public class ExternalLoadBalancerDeviceVO { } } - public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, boolean managed, long parentHostId) { - this(hostId, physicalNetworkId, provider_name, device_name); + public ExternalLoadBalancerDeviceVO(long hostId, long physicalNetworkId, String provider_name, String device_name, + long capacity, boolean dedicated, boolean inline, boolean managed, long parentHostId) { + this(hostId, physicalNetworkId, provider_name, device_name, capacity, dedicated, inline); this.isManagedDevice = managed; this.parentHostId = parentHostId; } @@ -175,6 +183,14 @@ public class ExternalLoadBalancerDeviceVO { this.isManagedDevice = managed; } + public boolean getIsInLineMode () { + return isInlineMode; + } + + public void setIsInlineMode(boolean inline) { + this.isInlineMode = inline; + } + public boolean getIsDedicatedDevice() { return isDedicatedDevice; } diff --git a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java index 02f931bc334..b5fe851ef31 100644 --- a/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java +++ b/server/src/com/cloud/network/element/NetscalerExternalLoadBalancerElement.java @@ -19,6 +19,7 @@ package com.cloud.network.element; +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -43,7 +44,10 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientNetworkCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; +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.ExternalLoadBalancerDeviceVO; @@ -69,7 +73,10 @@ import com.cloud.network.resource.NetscalerResource; import com.cloud.offering.NetworkOffering; import com.cloud.resource.ServerResource; import com.cloud.utils.component.Inject; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.UrlUtil; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; @@ -91,6 +98,7 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe @Inject NetworkExternalLoadBalancerDao _networkLBDao; @Inject PhysicalNetworkDao _physicalNetworkDao; @Inject NetworkDao _networkDao; + @Inject HostDetailsDao _detailsDao; private boolean canHandle(Network config) { if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) { @@ -189,7 +197,8 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe throw new InvalidParameterValueException("Invalid Netscaler device type"); } - return addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, (ServerResource) new NetscalerResource()); + ExternalLoadBalancerDeviceVO lbDeviceVO = addExternalLoadBalancer(cmd.getPhysicalNetworkId(), cmd.getUrl(), cmd.getUsername(), cmd.getPassword(), deviceName, (ServerResource) new NetscalerResource()); + return lbDeviceVO; } @Override @@ -208,14 +217,26 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe public ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(ConfigureNetscalerLoadBalancerCmd cmd) { Long lbDeviceId = cmd.getLoadBalancerDeviceId(); Boolean dedicatedUse = cmd.getLoadBalancerDedicated(); + Boolean inline = cmd.getLoadBalancerInline(); Long capacity = cmd.getLoadBalancerCapacity(); + try { + return configureNetscalerLoadBalancer(lbDeviceId, capacity, inline, dedicatedUse); + } catch (Exception e) { + throw new CloudRuntimeException("failed to configure netscaler device due to " + e.getMessage()); + } + } + + @DB + private ExternalLoadBalancerDeviceVO configureNetscalerLoadBalancer(long lbDeviceId, Long capacity, Boolean inline, Boolean dedicatedUse) { ExternalLoadBalancerDeviceVO lbDeviceVo = _lbDeviceDao.findById(lbDeviceId); + Map lbDetails = _detailsDao.findDetails(lbDeviceVo.getHostId()); + if ((lbDeviceVo == null) || !isNetscalerDevice(lbDeviceVo.getDeviceName())) { throw new InvalidParameterValueException("No netscaler device found with ID: " + lbDeviceId); } - if (dedicatedUse != null || capacity != null) { + if (dedicatedUse != null || capacity != null || inline != null) { String deviceName = lbDeviceVo.getDeviceName(); if (NetworkDevice.NetscalerSDXLoadBalancer.getName().equalsIgnoreCase(deviceName)) { @@ -230,25 +251,49 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe List networks = _networkLBDao.listByLoadBalancerDeviceId(lbDeviceId); if ((networks != null) && !networks.isEmpty()) { if (capacity < networks.size()) { - throw new CloudRuntimeException("There are more number of networks already using this netscalr device than configured capacity"); + throw new CloudRuntimeException("There are more number of networks already using this netscaler device than configured capacity"); } if (dedicatedUse !=null && dedicatedUse == true) { - throw new CloudRuntimeException("There are networks already using this netscalr device to make device dedicated"); + throw new CloudRuntimeException("There are networks already using this netscaler device to make device dedicated"); } - } - if (capacity != null) { - lbDeviceVo.setCapacity(capacity); - } - - if(dedicatedUse != null) { - lbDeviceVo.setIsDedicatedDevice(dedicatedUse); + if (inline != null) { + boolean _setInline = Boolean.parseBoolean((String) lbDetails.get("inline")); + if (inline != _setInline) { + throw new CloudRuntimeException("There are networks already using this netscaler device to change the device inline or side-by-side configuration"); + } + } } } + if (capacity != null) { + lbDeviceVo.setCapacity(capacity); + } + + if(dedicatedUse != null) { + lbDeviceVo.setIsDedicatedDevice(dedicatedUse); + } + + if (inline != null && inline == true) { + lbDeviceVo.setIsInlineMode(true); + lbDetails.put("inline", "true"); + } else { + lbDeviceVo.setIsInlineMode(false); + lbDetails.put("inline", "false"); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + lbDeviceVo.setState(LBDeviceState.Enabled); _lbDeviceDao.update(lbDeviceId, lbDeviceVo); + + _detailsDao.persist(lbDeviceVo.getHostId(), lbDetails); + HostVO host = _hostDao.findById(lbDeviceVo.getHostId()); + txn.commit(); + + _agentMgr.reconnect(host.getId()); return lbDeviceVo; } @@ -313,10 +358,17 @@ public class NetscalerExternalLoadBalancerElement extends ExternalLoadBalancerDe @Override public NetscalerLoadBalancerResponse createNetscalerLoadBalancerResponse(ExternalLoadBalancerDeviceVO lbDeviceVO) { NetscalerLoadBalancerResponse response = new NetscalerLoadBalancerResponse(); + Host lbHost = _hostDao.findById(lbDeviceVO.getHostId()); + Map lbDetails = _detailsDao.findDetails(lbDeviceVO.getHostId()); + response.setId(lbDeviceVO.getId()); + response.setIpAddress(lbHost.getPrivateIpAddress()); response.setPhysicalNetworkId(lbDeviceVO.getPhysicalNetworkId()); + response.setPublicInterface(lbDetails.get("publicInterface")); + response.setPrivateInterface(lbDetails.get("privateInterface")); response.setDeviceName(lbDeviceVO.getDeviceName()); response.setDeviceCapacity(lbDeviceVO.getCapacity()); + response.setInlineMode(lbDeviceVO.getIsInLineMode()); response.setDedicatedLoadBalancer(lbDeviceVO.getIsDedicatedDevice()); response.setProvider(lbDeviceVO.getProviderName()); response.setDeviceState(lbDeviceVO.getState().name()); diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index ae0ab2ed9d3..ff311d9c454 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1950,6 +1950,7 @@ CREATE TABLE `cloud`.`external_load_balancer_devices` ( `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', `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',