package org.openstack.atlas.adapter.zxtm;
import com.zxtm.service.client.*;
import org.apache.axis.AxisFault;
import org.apache.axis.types.UnsignedInt;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openstack.atlas.adapter.LoadBalancerEndpointConfiguration;
import org.openstack.atlas.adapter.exceptions.*;
import org.openstack.atlas.adapter.helpers.*;
import org.openstack.atlas.adapter.service.ReverseProxyLoadBalancerAdapter;
import org.openstack.atlas.service.domain.entities.*;
import org.openstack.atlas.service.domain.pojos.*;
import org.openstack.atlas.service.domain.util.Constants;
import org.openstack.atlas.util.ca.StringUtils;
import org.openstack.atlas.util.ca.zeus.ZeusCrtFile;
import org.openstack.atlas.util.ca.zeus.ZeusUtils;
import org.openstack.atlas.util.converters.StringConverter;
import org.openstack.atlas.util.ip.exception.IPStringConversionException;
import org.springframework.stereotype.Component;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.*;
import static org.openstack.atlas.service.domain.entities.SessionPersistence.NONE;
@Component
public class ZxtmAdapterImpl implements ReverseProxyLoadBalancerAdapter {
public static Log LOG = LogFactory.getLog(ZxtmAdapterImpl.class.getName());
public static final LoadBalancerAlgorithm DEFAULT_ALGORITHM = LoadBalancerAlgorithm.RANDOM;
public static final String SOURCE_IP = "SOURCE_IP";
public static final String HTTP_COOKIE = "HTTP_COOKIE";
public static final String SSL_ID = "SSL_ID";
public static final String RATE_LIMIT_HTTP = "rate_limit_http";
public static final String RATE_LIMIT_NON_HTTP = "rate_limit_nonhttp";
public static final String CONTENT_CACHING = "content_caching";
public static final String XFF = "add_x_forwarded_for_header";
public static final String XFP = "add_x_forwarded_proto";
public static final String XFPORT = "add_x_forwarded_port";
public static final String HTTPS_REDIRECT = "force_https_redirect";
public static final VirtualServerRule ruleRateLimitHttp = new VirtualServerRule(RATE_LIMIT_HTTP, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleRateLimitNonHttp = new VirtualServerRule(RATE_LIMIT_NON_HTTP, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleXForwardedPort = new VirtualServerRule(XFPORT, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleXForwardedFor = new VirtualServerRule(XFF, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleXForwardedProto = new VirtualServerRule(XFP, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleContentCaching = new VirtualServerRule(CONTENT_CACHING, true, VirtualServerRuleRunFlag.run_every);
public static final VirtualServerRule ruleForceHttpsRedirect = new VirtualServerRule(HTTPS_REDIRECT, true, VirtualServerRuleRunFlag.run_every);
protected static final ZeusUtils zeusUtil;
public static final String NON_HTTP_LOG_FORMAT = "%v %t %h %A:%p %n %B %b %T";
public static final String HTTP_LOG_FORMAT = "%v %{Host}i %h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\" %n";
static {
zeusUtil = new ZeusUtils();
}
@Override
public ZxtmServiceStubs getServiceStubs(LoadBalancerEndpointConfiguration config) throws AxisFault {
return ZxtmServiceStubs.getServiceStubs(config.getEndpointUrl(), config.getUsername(), config.getPassword());
}
@Override
public ZxtmServiceStubs getStatsStubs(URL endpoint, LoadBalancerEndpointConfiguration config) throws AxisFault {
return ZxtmServiceStubs.getServiceStubs(endpoint, config.getUsername(), config.getPassword());
}
@Override
public void createLoadBalancer(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String virtualServerName = ZxtmNameBuilder.genVSName(lb);
final String poolName = ZxtmNameBuilder.genVSName(lb.getId(), lb.getAccountId());
final VirtualServerBasicInfo vsInfo;
LoadBalancerAlgorithm algorithm = lb.getAlgorithm() == null ? DEFAULT_ALGORITHM : lb.getAlgorithm();
final String rollBackMessage = "Create load balancer request canceled.";
LOG.debug(String.format("Creating load balancer '%s'...", virtualServerName));
try {
createNodePool(config, lb.getId(), lb.getAccountId(), lb.getNodes(), algorithm);
setNodesPriorities(config, poolName, lb);
} catch (Exception e) {
deleteNodePool(serviceStubs, poolName);
throw new ZxtmRollBackException(rollBackMessage, e);
}
try {
LOG.debug(String.format("Adding virtual server '%s'...", virtualServerName));
vsInfo = new VirtualServerBasicInfo(lb.getPort(), ZxtmConversionUtils.mapProtocol(lb.getProtocol()), poolName);
serviceStubs.getVirtualServerBinding().addVirtualServer(new String[]{virtualServerName}, new VirtualServerBasicInfo[]{vsInfo});
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(new String[]{virtualServerName}, new boolean[]{true});
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(new String[]{virtualServerName}, new boolean[]{true});
LOG.info(String.format("Virtual server '%s' successfully added.", virtualServerName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
throw new ObjectAlreadyExists();
}
deleteVirtualServer(serviceStubs, virtualServerName);
deleteNodePool(serviceStubs, poolName);
throw new ZxtmRollBackException(rollBackMessage, e);
}
try {
addVirtualIps(config, lb, virtualServerName);
//Verify that the server is not listening to all addresses, zeus does this by default and is an unwanted behaviour.
isVSListeningOnAllAddresses(serviceStubs, virtualServerName, poolName);
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerName}, new boolean[]{true});
updateLoadBalancerAttributes(config, serviceStubs, lb, virtualServerName);
if (lb.getTimeout() != null) {
updateTimeout(config, lb);
}
//Added rules for HTTP LB
if (lb.getProtocol().equals(LoadBalancerProtocol.HTTP)) {
TrafficScriptHelper.addXForwardedPortScriptIfNeeded(serviceStubs);
attachXFPORTRuleToVirtualServer(serviceStubs, virtualServerName);
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(new String[]{virtualServerName}, new boolean[]{true});
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(new String[]{virtualServerName}, new boolean[]{true});
setDefaultErrorFile(config, lb);
}
} catch (Exception e) {
deleteLoadBalancer(config, lb);
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Load balancer '%s' successfully created.", virtualServerName));
}
@Override
public void updateLoadBalancer(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException, ZxtmRollBackException, StmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String name = ZxtmNameBuilder.genVSName(loadBalancer);
final String rollBackMessage = "Sync load balancer request canceled.";
if (!Arrays.asList(serviceStubs.getPoolBinding().getPoolNames()).contains(name)) {
LOG.debug(String.format("Adding node pool '%s'...", name));
createNodePool(config, loadBalancer.getId(), loadBalancer.getAccountId(), loadBalancer.getNodes(), loadBalancer.getAlgorithm());
LOG.info(String.format("Node pool '%s' successfully added.", name));
} else {
setLoadBalancingAlgorithm(config, loadBalancer.getId(), loadBalancer.getAccountId(), loadBalancer.getAlgorithm());
setNodes(config, loadBalancer);
serviceStubs.getPoolBinding().setPassiveMonitoring(new String[]{name}, new boolean[]{false});
}
if (!(loadBalancer.isHttpsRedirect() != null && loadBalancer.isHttpsRedirect() && loadBalancer.hasSsl())
&& !Arrays.asList(serviceStubs.getVirtualServerBinding().getVirtualServerNames()).contains(name)) {
LOG.debug(String.format("Adding virtual server '%s'...", name));
VirtualServerBasicInfo vsInfo = new VirtualServerBasicInfo(loadBalancer.getPort(), ZxtmConversionUtils.mapProtocol(loadBalancer.getProtocol()), name);
serviceStubs.getVirtualServerBinding().addVirtualServer(new String[]{name}, new VirtualServerBasicInfo[]{vsInfo});
LOG.info(String.format("Virtual server '%s' successfully added.", name));
}
if (Arrays.asList(serviceStubs.getVirtualServerBinding().getVirtualServerNames()).contains(name)) {
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(new String[]{name}, new boolean[]{true});
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(new String[]{name}, new boolean[]{true});
if (!loadBalancer.getProtocol().equals(LoadBalancerProtocol.HTTP)) {
try {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{name}, new String[][]{{ZxtmAdapterImpl.ruleXForwardedPort.getName()}});
} catch (InvalidInput e) {
LOG.info(String.format("X-Forwarded-Port rule doesn't exist on virtual server '%s': ignoring....", name));
}
}
serviceStubs.getVirtualServerBinding().setProtocol(new String[]{name}, new VirtualServerProtocol[]{ZxtmConversionUtils.mapProtocol(loadBalancer.getProtocol())});
serviceStubs.getVirtualServerBinding().setPort(new String[]{name}, new UnsignedInt[]{new UnsignedInt(loadBalancer.getPort())});
addVirtualIps(config, loadBalancer, name);
try {
isVSListeningOnAllAddresses(serviceStubs, name, name);
} catch (Exception e) {
throw new ZxtmRollBackException(rollBackMessage, e);
}
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{name}, new boolean[]{true});
if (loadBalancer.getProtocol().equals(LoadBalancerProtocol.HTTP)) {
TrafficScriptHelper.addXForwardedPortScriptIfNeeded(serviceStubs);
attachXFPORTRuleToVirtualServer(serviceStubs, name);
}
}
syncLoadBalancerAttributes(config, serviceStubs, loadBalancer, name); // This creates the RedirectVS as a side-effect if it needs to exist
if (loadBalancer.getTimeout() != null) {
updateTimeout(config, loadBalancer);
}
if (loadBalancer.getSslTermination() != null && loadBalancer.isUsingSsl()) {
ZeusSslTermination sslTerm = new ZeusSslTermination();
sslTerm.setCertIntermediateCert(loadBalancer.getSslTermination().getCertificate());
sslTerm.setSslTermination(loadBalancer.getSslTermination());
updateSslTermination(config, loadBalancer, sslTerm);
for (CertificateMapping certificateMapping : loadBalancer.getCertificateMappings()) {
updateCertificateMapping(config, loadBalancer.getId(), loadBalancer.getAccountId(), certificateMapping);
}
}
if (loadBalancer.getUserPages() != null && loadBalancer.getUserPages().getErrorpage() != null) {
setErrorFile(config, loadBalancer, loadBalancer.getUserPages().getErrorpage());
} else {
setDefaultErrorFile(config, loadBalancer);
}
LOG.info(String.format("Load balancer '%s' successfully synced.", name));
}
private void createRedirectVirtualServer(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String virtualServerName = ZxtmNameBuilder.genRedirectVSName(lb);
final String poolName = "discard";
final VirtualServerBasicInfo vsInfo;
final String rollBackMessage = "Create load balancer request canceled.";
LOG.debug(String.format("Creating load balancer '%s'...", virtualServerName));
try {
LOG.debug(String.format("Adding virtual server '%s'...", virtualServerName));
vsInfo = new VirtualServerBasicInfo(80, VirtualServerProtocol.http, poolName);
serviceStubs.getVirtualServerBinding().addVirtualServer(new String[]{virtualServerName}, new VirtualServerBasicInfo[]{vsInfo});
LOG.info(String.format("Virtual server '%s' successfully added.", virtualServerName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
throw new ObjectAlreadyExists();
}
deleteVirtualServer(serviceStubs, virtualServerName);
throw new ZxtmRollBackException(rollBackMessage, e);
}
try {
addVirtualIps(config, lb, virtualServerName);
//Verify that the server is not listening to all addresses, zeus does this by default and is an unwanted behaviour.
isVSListeningOnAllAddresses(serviceStubs, virtualServerName, poolName);
TrafficScriptHelper.addForceHttpsRedirectScriptIfNeeded(serviceStubs);
attachForceHttpsRedirectRuleToVirtualServer(serviceStubs, virtualServerName);
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerName}, new boolean[]{true});
updateLoadBalancerAttributes(config, serviceStubs, lb, virtualServerName);
if (lb.getTimeout() != null) {
updateTimeout(config, lb);
}
} catch (Exception e) {
deleteVirtualServer(serviceStubs, virtualServerName);
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Load balancer '%s' successfully created.", virtualServerName));
}
private void createSecureVirtualServer(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String rollBackMessage = "Create load balancer request canceled.";
final String secureVsName;
final String vsName;
final String poolName;
final VirtualServerBasicInfo vsInfo;
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
secureVsName = ZxtmNameBuilder.genSslVSName(lb.getId(), lb.getAccountId());
vsName = ZxtmNameBuilder.genVSName(lb.getId(), lb.getAccountId());
//Same name, but differentiate for clarity
poolName = vsName;
String vsRedirectName = ZxtmNameBuilder.genRedirectVSName(vsName);
boolean isRedirectServer = lb.isHttpsRedirect() != null && lb.isHttpsRedirect() == true;
String vsNameAltered = isRedirectServer ? vsRedirectName : vsName;
LOG.debug(String.format("Adding virtual server '%s'...", secureVsName));
vsInfo = new VirtualServerBasicInfo(lb.getSslTermination().getSecurePort(), ZxtmConversionUtils.mapProtocol(lb.getProtocol()), poolName);
serviceStubs.getVirtualServerBinding().addVirtualServer(new String[]{secureVsName}, new VirtualServerBasicInfo[]{vsInfo});
LOG.info(String.format("Virtual server '%s' successfully added.", secureVsName));
try {
addVirtualIps(config, lb, secureVsName);
//Verify that the server is not listening to all addresses, zeus does this by default and is an unwanted behaviour.
isVSListeningOnAllAddresses(serviceStubs, secureVsName, poolName);
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{secureVsName}, new boolean[]{true});
updateLoadBalancerAttributes(config, serviceStubs, lb, secureVsName);
if (lb.getRateLimit() != null) {
setRateLimit(config, secureVsName, lb.getRateLimit());
}
//Added rules for HTTP LB
if (lb.getProtocol().equals(LoadBalancerProtocol.HTTP)) {
TrafficScriptHelper.addXForwardedPortScriptIfNeeded(serviceStubs);
attachXFPORTRuleToVirtualServer(serviceStubs, secureVsName);
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(new String[]{secureVsName}, new boolean[]{true});
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(new String[]{secureVsName}, new boolean[]{true});
//
// TrafficScriptHelper.addXForwardedProtoScriptIfNeeded(serviceStubs);
// attachXFPRuleToVirtualServer(serviceStubs, secureVsName);
LOG.info(String.format("Enabling SSL Headers for virtual server: %s", secureVsName));
serviceStubs.getVirtualServerBinding().setSSLHeaders(new String[]{secureVsName}, new boolean[]{true});
LOG.info(String.format("Disabling HOST Header rewrite on secure virtual server: %s", secureVsName));
VirtualServerLocationDefaultRewriteMode never = VirtualServerLocationDefaultRewriteMode.never;
serviceStubs.getVirtualServerBinding().setLocationDefaultRewriteMode(new String[]{secureVsName}, new VirtualServerLocationDefaultRewriteMode[]{never});
LOG.info(String.format("Succesfully disabled HOST Header rewrite on secure virtual server: %s", secureVsName));
String[] errorFile;
errorFile = serviceStubs.getVirtualServerBinding().getErrorFile(new String[]{vsNameAltered});
// efContents = serviceStubs.getZxtmConfExtraBinding().getFile(new String[]{poolName});
if (errorFile[0].equals("Default") || errorFile[0].equals(Constants.DEFAULT_ERRORFILE)) {
setDefaultErrorFile(config, secureVsName);
} else {
setErrorFile(config, secureVsName, new String(serviceStubs.getZxtmConfExtraBinding().downloadFile(errorFile[0])));
}
}
} catch (Exception e) {
if (e instanceof ObjectAlreadyExists) {
throw new ObjectAlreadyExists();
} else {
deleteVirtualServer(serviceStubs, secureVsName);
removeSslTermination(config, lb);
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
LOG.info(String.format("Secure virtual server '%s' successfully created.", secureVsName));
}
private void repurposeVirtualServerForHttpsRedirect(LoadBalancer lb, ZxtmServiceStubs serviceStubs)
throws InsufficientRequestException {
if (lb.getSslTermination().isSecureTrafficOnly() != true) return;
String virtualServerName = ZxtmNameBuilder.genVSName(lb);
String virtualServerRedirectName = ZxtmNameBuilder.genRedirectVSName(lb);
try {
TrafficScriptHelper.addForceHttpsRedirectScriptIfNeeded(serviceStubs);
attachForceHttpsRedirectRuleToVirtualServer(serviceStubs, virtualServerName);
removeXFPORTRuleFromVirtualServer(serviceStubs, virtualServerName);
serviceStubs.getVirtualServerBinding().renameVirtualServer(new String[]{virtualServerName}, new String[]{virtualServerRedirectName});
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerRedirectName}, new boolean[]{true});
} catch (RemoteException e) {
e.printStackTrace();
//throw rollback?
}
}
private void restoreVirtualServerFromHttpsRedirect(LoadBalancer lb, ZxtmServiceStubs serviceStubs)
throws InsufficientRequestException {
String virtualServerName = ZxtmNameBuilder.genVSName(lb);
String virtualServerRedirectName = ZxtmNameBuilder.genRedirectVSName(lb);
try {
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerRedirectName}, new boolean[]{false});
serviceStubs.getVirtualServerBinding().renameVirtualServer(new String[]{virtualServerRedirectName}, new String[]{virtualServerName});
removeForceHttpsRedirectRuleFromVirtualServer(serviceStubs, virtualServerName);
attachXFPORTRuleToVirtualServer(serviceStubs, virtualServerName);
} catch (RemoteException e) {
e.printStackTrace();
//throw rollback?
}
}
private void syncLoadBalancerAttributes(LoadBalancerEndpointConfiguration config, ZxtmServiceStubs serviceStubs, LoadBalancer lb, String virtualServerName)
throws ZxtmRollBackException, InsufficientRequestException, RemoteException {
String redirectName = ZxtmNameBuilder.genRedirectVSName(lb);
if (lb.getSessionPersistence() != null && !lb.getSessionPersistence().equals(NONE)) {
setSessionPersistence(config, lb.getId(), lb.getAccountId(), lb.getSessionPersistence());
} else if ((lb.getSessionPersistence() == null || lb.getSessionPersistence().equals(NONE) || lb.hasSsl())
&& serviceStubs.getPoolBinding().getPersistence(new String[]{virtualServerName}).length != 0) {
removeSessionPersistence(config, lb.getId(), lb.getAccountId());
}
if (lb.getHealthMonitor() != null) {
updateHealthMonitor(config, lb);
} else if (lb.getHealthMonitor() == null && Arrays.asList(serviceStubs.getMonitorBinding().getCustomMonitorNames()).contains(virtualServerName)) {
removeHealthMonitor(config, lb);
}
if (lb.getConnectionLimit() != null) {
updateConnectionThrottle(config, lb);
} else if (Arrays.asList(serviceStubs.getProtectionBinding().getProtectionNames()).contains(virtualServerName)) {
deleteConnectionThrottle(config, lb);
}
if (lb.isConnectionLogging() == null) {
lb.setConnectionLogging(false);
}
updateConnectionLogging(config, lb);
if (lb.isContentCaching() == null) {
lb.setContentCaching(false);
}
updateContentCaching(config, lb);
if (lb.getAccessLists() != null && !lb.getAccessLists().isEmpty()) {
updateAccessList(config, lb);
} else if (Arrays.asList(serviceStubs.getProtectionBinding().getProtectionNames()).contains(virtualServerName)) {
deleteAccessList(config, virtualServerName);
}
if (lb.isHalfClosed() == null) {
lb.setHalfClosed(false);
}
updateHalfClosed(config, lb);
if ((lb.isHttpsRedirect() != null && !virtualServerName.equals(redirectName))
|| (lb.isHttpsRedirect() == null && Arrays.asList(
serviceStubs.getVirtualServerBinding().getVirtualServerNames()).contains(redirectName))) {
updateHttpsRedirect(config, lb);
}
}
private void updateLoadBalancerAttributes(LoadBalancerEndpointConfiguration config, ZxtmServiceStubs serviceStubs, LoadBalancer lb, String virtualServerName) throws ZxtmRollBackException, InsufficientRequestException, RemoteException {
/* UPDATE REST OF LOADBALANCER CONFIG */
if (lb.getSessionPersistence() != null && !lb.getSessionPersistence().equals(NONE) && !lb.hasSsl()) {
//TODO: refactor to take lb only, right now its a pool item and only updates in one place...
//sessionPersistence is a pool item
setSessionPersistence(config, lb.getId(), lb.getAccountId(), lb.getSessionPersistence());
}
if (lb.getHealthMonitor() != null && !lb.hasSsl()) {
updateHealthMonitor(config, lb);
}
//VirtualServer items
if (lb.getConnectionLimit() != null) {
updateConnectionThrottle(config, lb);
}
if (lb.isConnectionLogging() != null && lb.isConnectionLogging()) {
updateConnectionLogging(config, lb);
}
if (lb.isContentCaching() != null && lb.isContentCaching()) {
updateContentCaching(config, lb);
}
if (lb.getAccessLists() != null && !lb.getAccessLists().isEmpty()) {
updateAccessList(config, lb);
}
if (lb.isHalfClosed() != null) {
updateHalfClosed(config, lb);
}
if (lb.isHttpsRedirect() != null && !virtualServerName.equals(ZxtmNameBuilder.genRedirectVSName(lb))) {
updateHttpsRedirect(config, lb);
}
}
private void isVSListeningOnAllAddresses(ZxtmServiceStubs serviceStubs, String virtualServerName, String poolName) throws RemoteException, VirtualServerListeningOnAllAddressesException {
boolean[] isListening = serviceStubs.getVirtualServerBinding().getListenOnAllAddresses(new String[]{virtualServerName});
//If The VS is listening on all addresses, rollback pools and VS, Log an exception...
if (isListening[0]) {
deleteNodePool(serviceStubs, poolName);
deleteVirtualServer(serviceStubs, virtualServerName);
throw new VirtualServerListeningOnAllAddressesException(String.format("The Virtual Server %s was found to be listening on all IP addresses.", virtualServerName));
}
}
@Override
public void setNodesPriorities(LoadBalancerEndpointConfiguration config, String poolName, LoadBalancer lb) throws RemoteException {
Set<Node> nodes = lb.getNodes();
if (nodes == null || nodes.isEmpty()) return;
ZeusNodePriorityContainer znpc = new ZeusNodePriorityContainer(nodes);
String[] poolNames = new String[]{poolName};
LOG.debug(String.format("setNodePriority for pool %s priority=%s Starting....", poolNames[0], znpc));
ZxtmServiceStubs stubs = getServiceStubs(config);
PoolPriorityValueDefinition[][] priorities = znpc.getPriorityValues();
try {
if (priorities != null) {
stubs.getPoolBinding().setNodesPriorityValue(poolNames, znpc.getPriorityValues());
if (znpc.hasSecondary()) {
boolean[] setTrue = new boolean[]{true};
stubs.getPoolBinding().setPriorityEnabled(poolNames, setTrue);
} else {
boolean[] setFalse = new boolean[]{false};
stubs.getPoolBinding().setPriorityEnabled(poolNames, setFalse);
}
}
} catch (InvalidInput ex) {
LOG.warn(String.format("Nodes %s not updated as it no longer exist...", poolNames[0]));
}
LOG.debug(String.format("setNodePriority for pool %s priority=%s Finished....", poolNames[0], znpc));
}
@Override
public void updateCertificateMapping(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, CertificateMapping certMappingToUpdate) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String virtualServerNameSecure = ZxtmNameBuilder.genSslVSName(lbId, accountId);
final String certificateName = ZxtmNameBuilder.generateCertificateName(lbId, accountId, certMappingToUpdate.getId());
String userKey = certMappingToUpdate.getPrivateKey();
String userCrt = certMappingToUpdate.getCertificate();
String imdCrt = certMappingToUpdate.getIntermediateCertificate();
ZeusCrtFile zeusCrtFile = zeusUtil.buildZeusCrtFileLbassValidation(userKey, userCrt, imdCrt);
if (zeusCrtFile.hasFatalErrors()) {
String errors = StringUtils.joinString(zeusCrtFile.getFatalErrorList(), ",");
String msg = String.format("ZeusCrtFile generation failure: %s", errors);
throw new InsufficientRequestException(msg);
}
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
VirtualServerBindingStub virtualServerService = serviceStubs.getVirtualServerBinding();
CatalogSSLCertificatesBindingStub certificateCatalogService = serviceStubs.getZxtmCatalogSSLCertificatesBinding();
try {
LOG.debug(String.format("Removing certificate mappings for load balancer '%d' that use certificate '%s'...", lbId, certificateName));
VirtualServerSSLSite[][] sslSites = virtualServerService.getSSLSites(new String[]{virtualServerNameSecure});
List<String> siteIpsArray = new ArrayList<String>();
for (VirtualServerSSLSite sslSite : sslSites[0]) {
if (sslSite.getCertificate().equals(certificateName)) {
LOG.debug(String.format("Marking SSLSite with host name '%s' for removal for load balancer '%d' that uses certificate '%s'...", sslSite.getDest_address(), lbId, certificateName));
siteIpsArray.add(sslSite.getDest_address());
}
}
String[] siteIps = new String[siteIpsArray.size()];
siteIpsArray.toArray(siteIps);
virtualServerService.deleteSSLSites(new String[]{virtualServerNameSecure}, new String[][]{siteIps});
LOG.debug(String.format("Successfully removed certificate mappings for load balancer '%d' that used certificate '%s'.", lbId, certificateName));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Cannot remove certificate mappings for load balancer '%d' that use certificate '%s' as the virtual server does not exist. Ignoring...", lbId, certificateName));
} catch (AxisFault axisFault) {
// Stingray should have returned a proper error, but doesn't sadly. Hence, why we parse the error message.
if (axisFault.getFaultString().contains("could not be found")) {
LOG.debug(String.format("Cannot remove certificate mappings for load balancer '%d' that use certificate '%s' as at least one mapping does not exist. Ignoring...", lbId, certificateName));
} else {
throw axisFault;
}
}
try {
LOG.debug(String.format("Removing certificate '%s' for certificate mapping '%d' for load balancer '%d'...", certificateName, certMappingToUpdate.getId(), lbId));
certificateCatalogService.deleteCertificate(new String[]{certificateName});
LOG.debug(String.format("Successfully removed certificate mapping '%d' for load balancer '%d'.", certMappingToUpdate.getId(), lbId));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Cannot remove certificate '%s' as it does not exist for certificate mapping '%d' for load balancer '%d'. Ignoring...", certificateName, certMappingToUpdate.getId(), lbId));
}
try {
LOG.debug(String.format("Importing certificate '%s' for certificate mapping '%d' for load balancer '%d'...", certificateName, certMappingToUpdate.getId(), lbId));
CertificateFiles certificateFiles = new CertificateFiles(zeusCrtFile.getPublic_cert(), zeusCrtFile.getPrivate_key());
certificateCatalogService.importCertificate(new String[]{certificateName}, new CertificateFiles[]{certificateFiles});
LOG.debug(String.format("Successfully imported certificate '%s' for certificate mapping '%d' for load balancer '%d'.", certificateName, certMappingToUpdate.getId(), lbId));
VirtualServerSSLSite sslSite = new VirtualServerSSLSite(certMappingToUpdate.getHostName(), certificateName);
LOG.debug(String.format("Attaching certificate mapping '%d' (certificate '%s') to load balancer %d (virtual server '%s')...", certMappingToUpdate.getId(), certificateName, lbId, virtualServerNameSecure));
virtualServerService.addSSLSites(new String[]{virtualServerNameSecure}, new VirtualServerSSLSite[][]{new VirtualServerSSLSite[]{sslSite}});
LOG.debug(String.format("Successfully attached certificate mapping '%d' (certificate '%s') to load balancer %d (virtual server '%s').", certMappingToUpdate.getId(), certificateName, lbId, virtualServerNameSecure));
} catch (AxisFault af) {
String message = String.format("Error updating certificate mapping '%d' (certificate '%s') for load balancer %d (virtual server '%s').", certMappingToUpdate.getId(), certificateName, lbId, virtualServerNameSecure);
LOG.error(message);
throw new ZxtmRollBackException(message, af);
}
}
@Override
public void deleteCertificateMapping(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, CertificateMapping certMappingToDelete) throws RemoteException, InsufficientRequestException, RollBackException {
final String virtualServerNameSecure = ZxtmNameBuilder.genSslVSName(lbId, accountId);
final String certificateName = ZxtmNameBuilder.generateCertificateName(lbId, accountId, certMappingToDelete.getId());
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
VirtualServerBindingStub virtualServerService = serviceStubs.getVirtualServerBinding();
CatalogSSLCertificatesBindingStub certificateCatalogService = serviceStubs.getZxtmCatalogSSLCertificatesBinding();
try {
LOG.debug(String.format("Removing certificate mapping with host name '%s' and id '%d' for load balancer '%d'...", certMappingToDelete.getHostName(), certMappingToDelete.getId(), lbId));
virtualServerService.deleteSSLSites(new String[]{virtualServerNameSecure}, new String[][]{new String[]{certMappingToDelete.getHostName()}});
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Cannot remove certificate with host name '%s' and id '%d' as it does not exist for load balancer '%d'. Ignoring...", certMappingToDelete.getHostName(), certMappingToDelete.getId(), lbId));
} catch (AxisFault axisFault) {
// Stingray should have returned a proper error, but doesn't sadly. Hence, why we parse the error message.
if (axisFault.getFaultString().contains("could not be found")) {
LOG.debug(String.format("Cannot remove certificate with host name '%s' and id '%d' as it does not exist for load balancer '%d'. Ignoring...", certMappingToDelete.getHostName(), certMappingToDelete.getId(), lbId));
} else {
throw axisFault;
}
}
try {
LOG.debug(String.format("Removing certificate '%s' for certificate mapping '%d' for load balancer '%d'...", certificateName, certMappingToDelete.getId(), lbId));
certificateCatalogService.deleteCertificate(new String[]{certificateName});
LOG.debug(String.format("Successfully removed certificate mapping '%d' for load balancer '%d'.", certMappingToDelete.getId(), lbId));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Cannot remove certificate '%s' as it does not exist for certificate mapping '%d' for load balancer '%d'. Ignoring...", certificateName, certMappingToDelete.getId(), lbId));
}
}
@Override
public void deleteLoadBalancer(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String virtualServerName = ZxtmNameBuilder.genVSName(loadBalancer);
final String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
final String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(loadBalancer.getId(), loadBalancer.getAccountId());
final String poolName = virtualServerName;
LOG.debug(String.format("Deleting load balancer '%s'", virtualServerName));
removeAndSetDefaultErrorFile(config, loadBalancer);
//If present, remove the secure virtual server (SSL Termination)
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
if (isSecureServer) {
removeSslTermination(config, loadBalancer);
}
deleteRateLimit(config, loadBalancer);
deleteVirtualServer(serviceStubs, virtualServerName);
deleteNodePool(serviceStubs, poolName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isRedirectServer)
{
deleteVirtualServer(serviceStubs, virtualRedirectServerName);
}
deleteProtectionCatalog(serviceStubs, poolName);
removeHealthMonitor(config, loadBalancer);
deleteTrafficIpGroups(serviceStubs, loadBalancer);
LOG.info(String.format("Successfully deleted load balancer '%s'.", virtualServerName));
}
private void deleteVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
try {
LOG.debug(String.format("Deleting virtual server '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().deleteVirtualServer(new String[]{virtualServerName});
LOG.debug(String.format("Virtual server '%s' successfully deleted.", virtualServerName));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Virtual server '%s' already deleted.", virtualServerName));
}
}
private void deleteNodePool(ZxtmServiceStubs serviceStubs, String poolName) throws RemoteException {
try {
LOG.debug(String.format("Deleting pool '%s'...", poolName));
serviceStubs.getPoolBinding().deletePool(new String[]{poolName});
LOG.info(String.format("Pool '%s' successfully deleted.", poolName));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Pool '%s' already deleted. Ignoring...", poolName));
} catch (ObjectInUse oiu) {
LOG.error(String.format("Pool '%s' is currently in use. Cannot delete.", poolName));
}
}
private void deleteProtectionCatalog(ZxtmServiceStubs serviceStubs, String poolName) throws RemoteException {
try {
LOG.info(String.format("Removing protection catalog from virtual server for: '%s'.", poolName));
serviceStubs.getVirtualServerBinding().setProtection(new String[]{poolName}, new String[]{""});
LOG.debug(String.format("Removed protection catalog from virtual server for: '%s'.", poolName));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Virtual server '%s' already deleted. not updating protection catalog on server, ignoring...", poolName));
}
try {
LOG.debug(String.format("Deleting service protection catalog '%s'...", poolName));
serviceStubs.getProtectionBinding().deleteProtection(new String[]{poolName});
LOG.info(String.format("Service protection catalog '%s' successfully deleted.", poolName));
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("Service protection catalog '%s' already deleted. Ignoring...", poolName));
} catch (ObjectInUse oiu) {
LOG.error(String.format("Service protection catalog '%s' currently in use. Cannot delete.", poolName));
}
}
private void deleteTrafficIpGroups(ZxtmServiceStubs serviceStubs, LoadBalancer lb) throws RemoteException, InsufficientRequestException {
for (LoadBalancerJoinVip loadBalancerJoinVip : lb.getLoadBalancerJoinVipSet()) {
LOG.info(String.format("About to remove traffic ip group for load balancer: %d on account: %d", lb.getId(), lb.getAccountId()));
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip.getVirtualIp());
deleteTrafficIpGroup(serviceStubs, trafficIpGroupName);
LOG.info(String.format("Traffic ip group: %s for load balancer: %d was removed..", trafficIpGroupName, lb.getId()));
}
for (LoadBalancerJoinVip6 loadBalancerJoinVip6 : lb.getLoadBalancerJoinVip6Set()) {
LOG.info(String.format("About to remove traffic ip group for load balancer: %d on account: %d", lb.getId(), lb.getAccountId()));
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip6.getVirtualIp());
deleteTrafficIpGroup(serviceStubs, trafficIpGroupName);
LOG.info(String.format("Traffic ip group: %s for load balancer: %d was removed..", trafficIpGroupName, lb.getId()));
}
}
private void deleteTrafficIpGroupsX(ZxtmServiceStubs serviceStubs, List<String> trafficIpGroups) throws RemoteException {
for (String trafficIpGroupName : trafficIpGroups) {
deleteTrafficIpGroup(serviceStubs, trafficIpGroupName);
}
}
private void deleteTrafficIpGroup(ZxtmServiceStubs serviceStubs, String trafficIpGroupName) throws RemoteException, InvalidOperation {
try {
LOG.debug(String.format("Deleting traffic ip group '%s'...", trafficIpGroupName));
serviceStubs.getTrafficIpGroupBinding().deleteTrafficIPGroup(new String[]{trafficIpGroupName});
LOG.info(String.format("Successfully deleted traffic ip group '%s'...", trafficIpGroupName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.debug(String.format("Traffic ip group '%s' already deleted. Ignoring...", trafficIpGroupName));
} else if (e instanceof ObjectInUse) {
LOG.debug(String.format("Traffic ip group '%s' is in use (i.e. shared). Skipping...", trafficIpGroupName));
} else if (!(e instanceof ObjectDoesNotExist) && !(e instanceof ObjectInUse)) {
LOG.debug(String.format("There was an unknown issues deleting traffic ip group: %s", trafficIpGroupName) + e.getMessage());
}
LOG.debug(String.format("There was an error removing traffic ip group: %s Message: %s Stack-Trace: %s", trafficIpGroupName, e.getMessage(), Arrays.toString(e.getStackTrace())));
}
}
@Override
public void updateProtocol(LoadBalancerEndpointConfiguration config, LoadBalancer lb) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Integer lbId = lb.getId();
Integer accountId = lb.getAccountId();
LoadBalancerProtocol protocol = lb.getProtocol();
String[] vsNames;
boolean[] enablesXF;
boolean[] disablesXF;
boolean connectionLogging;
if (lb.isConnectionLogging() == null) {
connectionLogging = false;
lb.setConnectionLogging(Boolean.FALSE);
} else {
//Keep a record
connectionLogging = lb.isConnectionLogging();
lb.setConnectionLogging(Boolean.FALSE);
}
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
enablesXF = new boolean[]{true, true};
disablesXF = new boolean[]{false, false};
if (isSecureServer && isRedirectServer) { //don't make any changes to the Redirect server here
vsNames = new String[1];
vsNames[0] = virtualSecureServerName;
enablesXF = new boolean[]{true};
disablesXF = new boolean[]{false};
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) { //don't make any changes to the Redirect server here
vsNames = new String[1];
vsNames[0] = virtualServerName;
enablesXF = new boolean[]{true};
disablesXF = new boolean[]{false};
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
enablesXF = new boolean[]{true};
disablesXF = new boolean[]{false};
}
try {
if (protocol.equals(LoadBalancerProtocol.HTTP)) {
if (SessionPersistence.NONE.equals(lb.getSessionPersistence()) || SessionPersistence.SSL_ID.equals(lb.getSessionPersistence())) {
removeSessionPersistence(config, lbId, accountId);
}
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(vsNames, enablesXF);
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(vsNames, enablesXF);
attachXFPORTRuleToVirtualServers(serviceStubs, vsNames);
} else {
if (SessionPersistence.NONE.equals(lb.getSessionPersistence()) || SessionPersistence.HTTP_COOKIE.equals(lb.getSessionPersistence())) {
removeSessionPersistence(config, lbId, accountId);
}
for (String vname : vsNames) {
serviceStubs.getVirtualServerBinding().setRules(new String[]{(vname)}, new VirtualServerRule[][]{{}});
}
updateContentCaching(config, lb);
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(vsNames, disablesXF);
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(vsNames, disablesXF);
}
} catch (Exception e) {
throw new ZxtmRollBackException(String.format("Update protocol request canceled for %s ", virtualServerName), e);
}
try {
// Drop rate-limit Rule if it exists
boolean rateLimitExists = false;
String[] rateNames = serviceStubs.getZxtmRateCatalogService().getRateNames();
for (String vsName : vsNames) {
for (String rateName : rateNames) {
if (rateName.equals(vsName)) {
rateLimitExists = true;
}
}
}
if (rateLimitExists) {
removeRateLimitRulesFromVirtualServers(serviceStubs, vsNames);
}
// Disable logging for protocol switch (keeping trevors commit)
updateConnectionLogging(config, lb);
LOG.debug(String.format("Updating protocol to '%s' for virtual server '%s'...", protocol.name(), virtualServerName));
serviceStubs.getVirtualServerBinding().setProtocol(new String[]{vsNames[0]}, new VirtualServerProtocol[]{ZxtmConversionUtils.mapProtocol(protocol)});
LOG.info(String.format("Successfully updated protocol for virtual server '%s'.", virtualServerName));
try {
if (protocol.equals(LoadBalancerProtocol.HTTP)) {
TrafficScriptHelper.addXForwardedPortScriptIfNeeded(serviceStubs);
attachXFPORTRuleToVirtualServers(serviceStubs, vsNames);
serviceStubs.getVirtualServerBinding().setAddXForwardedForHeader(vsNames, enablesXF);
serviceStubs.getVirtualServerBinding().setAddXForwardedProtoHeader(vsNames, enablesXF);
}
} catch (Exception ex) {
throw new ZxtmRollBackException("Update protocol request canceled.", ex);
}
// Re-add rate-limit Rule
if (rateLimitExists) {
attachRateLimitRulesToVirtualServers(serviceStubs, vsNames);
}
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot update protocol for virtual server '%s' as it does not exist.", virtualServerName), e);
}
throw new ZxtmRollBackException("Update protocol request canceled.", e);
}
try {
// Update log format to match protocol
if (connectionLogging) {
lb.setConnectionLogging(true);
}
updateConnectionLogging(config, lb);
} catch (Exception e) {
throw new ZxtmRollBackException("Update protocol request canceled.", e);
}
}
private void updateSecureServerWithTempPool(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws ZxtmRollBackException, InsufficientRequestException, RemoteException {
String poolName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
String tempPoolName = poolName + "_T";
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
LOG.debug(String.format("Creating temporary pool '%s' and setting nodes...", tempPoolName));
try {
serviceStubs.getPoolBinding().addPool(new String[]{tempPoolName}, NodeHelper.getIpAddressesFromNodes(loadBalancer.getNodes()));
} catch (ObjectAlreadyExists oae) {
LOG.info("Temporary pool already exists, ignoring...");
}
serviceStubs.getVirtualServerBinding().setDefaultPool(new String[]{poolName}, new String[]{tempPoolName});
}
private void reattachSecureServerWithTempPool(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws ZxtmRollBackException, InsufficientRequestException, RemoteException {
String poolName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
String nonSecurePoolName = ZxtmNameBuilder.genVSName(loadBalancer);
String tempPoolName = poolName + "_T";
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
LOG.debug(String.format("Removing temporary pool '%s' ...", tempPoolName));
// serviceStubs.getPoolBinding().addPool(new String[]{tempPoolName}, NodeHelper.getIpAddressesFromNodes(loadBalancer.getNodes()));
serviceStubs.getVirtualServerBinding().setDefaultPool(new String[]{poolName}, new String[]{nonSecurePoolName});
serviceStubs.getPoolBinding().deletePool(new String[]{tempPoolName});
}
@Override
public void updatePort(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, Integer port)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isRedirectServer && isSecureServer) {
virtualServerName = virtualRedirectServerName;
}
try {
LOG.debug(String.format("Updating port to '%d' for virtual server '%s'...", port, virtualServerName));
serviceStubs.getVirtualServerBinding().setPort(new String[]{virtualServerName}, new UnsignedInt[]{new UnsignedInt(port)});
LOG.info(String.format("Successfully updated port for virtual server '%s'.", virtualServerName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot update port for virtual server '%s' as it does not exist.", virtualServerName), e);
}
throw new ZxtmRollBackException("Update port request canceled.", e);
}
}
private void updatePort(LoadBalancerEndpointConfiguration config, String virtualServerName, Integer port) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
LOG.debug(String.format("Updating port to '%d' for virtual server '%s'...", port, virtualServerName));
serviceStubs.getVirtualServerBinding().setPort(new String[]{virtualServerName}, new UnsignedInt[]{new UnsignedInt(port)});
LOG.info(String.format("Successfully updated port for virtual server '%s'.", virtualServerName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot update port for virtual server '%s' as it does not exist.", virtualServerName), e);
} else {
throw new ZxtmRollBackException("Update port request canceled as there was an unexpected error...", e);
}
}
}
private void suspendUnsuspendVirtualServer(LoadBalancerEndpointConfiguration config, String virtualServerName, boolean isSuspended) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
boolean isEnabled = false;
isEnabled = !isSuspended;
try {
LOG.debug(String.format("Updating suspension to '%s' for virtual server '%s'...", isSuspended, virtualServerName));
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerName}, new boolean[]{isEnabled});
// LOG.info(String.format("Successfully updated suspension for virtual server '%s'.", virtualServerName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot suspend/unsuspend virtual server '%s' as it does not exist.", virtualServerName), e);
} else {
throw new ZxtmRollBackException("Suspend/unsuspend request canceled.", e);
}
}
}
@Override
public void setLoadBalancingAlgorithm(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, LoadBalancerAlgorithm algorithm)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
try {
LOG.debug(String.format("Setting load balancing algorithm to '%s' for node pool '%s'...", algorithm.name(), poolName));
serviceStubs.getPoolBinding().setLoadBalancingAlgorithm(new String[]{poolName}, new PoolLoadBalancingAlgorithm[]{ZxtmConversionUtils.mapAlgorithm(algorithm)});
LOG.info(String.format("Load balancing algorithm successfully set for node pool '%s'...", poolName));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot update algorithm for node pool '%s' as it does not exist.", poolName), e);
}
throw new ZxtmRollBackException("Update algorithm request canceled.", e);
}
}
@Override
public void addVirtualIps(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
addVirtualIps(config, lb, ZxtmNameBuilder.genVSName(lb));
if (lb.hasSsl()) {
addVirtualIps(config, lb, ZxtmNameBuilder.genSslVSName(lb));
}
}
public void addVirtualIps(LoadBalancerEndpointConfiguration config, LoadBalancer lb, String vsName)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String[] failoverTrafficManagers = config.getFailoverTrafficManagerNames().toArray(new String[config.getFailoverTrafficManagerNames().size()]);
final String rollBackMessage = "Add virtual ips request canceled.";
String[][] currentTrafficIpGroups;
List<String> updatedTrafficIpGroups = new ArrayList<String>();
List<String> newTrafficIpGroups = new ArrayList<String>();
LOG.debug(String.format("Adding virtual ips for virtual server '%s'...", vsName));
try {
// Obtain traffic groups currently associated with the virtual server
currentTrafficIpGroups = serviceStubs.getVirtualServerBinding().getListenTrafficIPGroups(new String[]{vsName});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot add virtual ips to virtual server %s as it does not exist. %s", vsName, e));
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
// Add current traffic ip groups to traffic ip group list
if (currentTrafficIpGroups != null) {
updatedTrafficIpGroups.addAll(Arrays.asList(currentTrafficIpGroups[0]));
}
// Add new traffic ip groups for IPv4 vips
for (LoadBalancerJoinVip loadBalancerJoinVipToAdd : lb.getLoadBalancerJoinVipSet()) {
String newTrafficIpGroup = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVipToAdd.getVirtualIp());
newTrafficIpGroups.add(newTrafficIpGroup);
updatedTrafficIpGroups.add(newTrafficIpGroup);
createTrafficIpGroup(config, serviceStubs, loadBalancerJoinVipToAdd.getVirtualIp().getIpAddress(), newTrafficIpGroup);
}
// Add new traffic ip groups for IPv6 vips
for (LoadBalancerJoinVip6 loadBalancerJoinVip6ToAdd : lb.getLoadBalancerJoinVip6Set()) {
String newTrafficIpGroup = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip6ToAdd.getVirtualIp());
newTrafficIpGroups.add(newTrafficIpGroup);
updatedTrafficIpGroups.add(newTrafficIpGroup);
try {
createTrafficIpGroup(config, serviceStubs, loadBalancerJoinVip6ToAdd.getVirtualIp().getDerivedIpString(), newTrafficIpGroup);
} catch (IPStringConversionException e) {
LOG.error("Rolling back newly created traffic ip groups...", e);
deleteTrafficIpGroupsX(serviceStubs, newTrafficIpGroups);
throw new ZxtmRollBackException("Cannot derive name from IPv6 virtual ip.", e);
}
}
try {
// Define the virtual server to listen on for every traffic ip group
serviceStubs.getVirtualServerBinding().setListenTrafficIPGroups(new String[]{vsName}, new String[][]{Arrays.copyOf(updatedTrafficIpGroups.toArray(), updatedTrafficIpGroups.size(), String[].class)});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error("Cannot add virtual ips to virtual server as it does not exist.", e);
}
LOG.error("Rolling back newly created traffic ip groups...", e);
deleteTrafficIpGroupsX(serviceStubs, newTrafficIpGroups);
throw new ZxtmRollBackException(rollBackMessage, e);
}
// TODO: Refactor and handle exceptions properly
// Enable and set failover traffic managers for traffic ip groups
for (String trafficIpGroup : updatedTrafficIpGroups) {
try {
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroup}, new boolean[]{true});
serviceStubs.getTrafficIpGroupBinding().addTrafficManager(new String[]{trafficIpGroup}, new String[][]{failoverTrafficManagers});
serviceStubs.getTrafficIpGroupBinding().setPassiveMachine(new String[]{trafficIpGroup}, new String[][]{failoverTrafficManagers});
} catch (ObjectDoesNotExist e) {
LOG.warn(String.format("Traffic ip group '%s' does not exist. Continuing...", trafficIpGroup));
}
}
LOG.info(String.format("Virtual ips successfully added for virtual server '%s'...", vsName));
}
/*
* A traffic ip group consists of only one virtual ip at this time.
*/
private void createTrafficIpGroup(LoadBalancerEndpointConfiguration config, ZxtmServiceStubs serviceStubs, String ipAddress, String newTrafficIpGroup) throws RemoteException {
final TrafficIPGroupsDetails details = new TrafficIPGroupsDetails(new String[]{ipAddress}, new String[]{config.getTrafficManagerName()});
try {
LOG.debug(String.format("Adding traffic ip group '%s'...", newTrafficIpGroup));
serviceStubs.getTrafficIpGroupBinding().addTrafficIPGroup(new String[]{newTrafficIpGroup}, new TrafficIPGroupsDetails[]{details});
LOG.info(String.format("Traffic ip group '%s' successfully added.", newTrafficIpGroup));
} catch (ObjectAlreadyExists oae) {
LOG.debug(String.format("Traffic ip group '%s' already exists. Ignoring...", newTrafficIpGroup));
}
}
@Override
public void deleteVirtualIp(LoadBalancerEndpointConfiguration config, LoadBalancer lb, Integer vipId)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
List<Integer> vipIds = new ArrayList<Integer>();
vipIds.add(vipId);
deleteVirtualIps(config, lb, vipIds);
}
@Override
public void deleteVirtualIps(LoadBalancerEndpointConfiguration config, LoadBalancer lb, List<Integer> vipIds)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String virtualServerName = ZxtmNameBuilder.genVSName(lb.getId(), lb.getAccountId());
String[][] currentTrafficIpGroups;
List<String> updatedTrafficIpGroupList = new ArrayList<String>();
String trafficIpGroupToDelete;
final String rollBackMessage = "Delete virtual ip request canceled.";
try {
currentTrafficIpGroups = serviceStubs.getVirtualServerBinding().getListenTrafficIPGroups(new String[]{virtualServerName});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error("Cannot delete virtual ip from virtual server as the virtual server does not exist.", e);
}
LOG.error(rollBackMessage + "Rolling back changes...", e);
throw new ZxtmRollBackException(rollBackMessage, e);
}
// Convert current traffic groups to array
List<String> trafficIpGroupNames = new ArrayList<String>();
for (String[] currentTrafficGroup : currentTrafficIpGroups) {
trafficIpGroupNames.addAll(Arrays.asList(currentTrafficGroup));
}
// Get traffic ip group to delete
List<String> trafficIpGroupNamesToDelete = new ArrayList<String>();
for (Integer vipIdToDelete : vipIds) {
trafficIpGroupNamesToDelete.add(ZxtmNameBuilder.generateTrafficIpGroupName(lb, vipIdToDelete));
}
// Exclude the traffic ip group to delete
for (String trafficIpGroupName : trafficIpGroupNames) {
if (!trafficIpGroupNamesToDelete.contains(trafficIpGroupName)) {
updatedTrafficIpGroupList.add(trafficIpGroupName);
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroupName}, new boolean[]{true});
}
}
try {
// Update the virtual server to listen on the updated traffic ip groups
serviceStubs.getVirtualServerBinding().setListenTrafficIPGroups(new String[]{virtualServerName}, new String[][]{Arrays.copyOf(updatedTrafficIpGroupList.toArray(), updatedTrafficIpGroupList.size(), String[].class)});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error("Cannot set traffic ip groups to virtual server as it does not exist.", e);
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
if (!trafficIpGroupNamesToDelete.isEmpty()) {
try {
deleteTrafficIpGroupsX(serviceStubs, trafficIpGroupNamesToDelete);
} catch (RemoteException re) {
LOG.error(rollBackMessage + "Rolling back changes...", re);
serviceStubs.getVirtualServerBinding().setListenTrafficIPGroups(new String[]{virtualServerName}, new String[][]{Arrays.copyOf(trafficIpGroupNamesToDelete.toArray(), trafficIpGroupNamesToDelete.size(), String[].class)});
serviceStubs.getTrafficIpGroupBinding().setEnabled(trafficIpGroupNames.toArray(new String[trafficIpGroupNames.size()]), generateBooleanArray(trafficIpGroupNames.size(), true));
throw new ZxtmRollBackException(rollBackMessage, re);
}
}
}
@Override
public void setRateLimit(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, RateLimit rateLimit) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
setRateLimit(config, ZxtmNameBuilder.genVSName(loadBalancer), rateLimit);
if (loadBalancer.hasSsl()) {
setRateLimit(config, ZxtmNameBuilder.genSslVSName(loadBalancer), rateLimit);
}
}
public void setRateLimit(LoadBalancerEndpointConfiguration config, String vsName, RateLimit rateLimit) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
LOG.debug(String.format("Adding a rate limit to load balancer...'%s'...", vsName));
serviceStubs.getZxtmRateCatalogService().addRate(new String[]{vsName});
serviceStubs.getZxtmRateCatalogService().setMaxRatePerSecond(new String[]{vsName}, new UnsignedInt[]{new UnsignedInt(rateLimit.getMaxRequestsPerSecond())});
LOG.info("Successfully added a rate limit to the rate limit pool.");
TrafficScriptHelper.addRateLimitScriptsIfNeeded(serviceStubs);
attachRateLimitRulesToVirtualServers(serviceStubs, new String[]{vsName});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot add rate limit for virtual server '%s' as it does not exist.", vsName));
}
throw new ZxtmRollBackException("Add rate limit request canceled.", e);
}
}
private void attachRateLimitRulesToVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug("Attach rules and enable them on the virtual server.");
VirtualServerRule rateLimitRule;
if (serviceStubs.getVirtualServerBinding().getProtocol(new String[]{virtualServerName})[0].equals(VirtualServerProtocol.http)) {
rateLimitRule = ZxtmAdapterImpl.ruleRateLimitHttp;
} else {
rateLimitRule = ZxtmAdapterImpl.ruleRateLimitNonHttp;
}
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{rateLimitRule}});
LOG.info("Rules attached to the VS, add rate limit successfully completed.");
}
private void attachRateLimitRulesToVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
attachRateLimitRulesToVirtualServer(serviceStubs, vsName);
}
}
private void removeRateLimitRulesFromVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Removing rate-limit rules from load balancer '%s'...", virtualServerName));
VirtualServerRule[][] virtualServerRules = serviceStubs.getVirtualServerBinding().getRules(new String[]{virtualServerName});
if (virtualServerRules.length > 0) {
for (VirtualServerRule virtualServerRule : virtualServerRules[0]) {
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleRateLimitHttp.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleRateLimitHttp.getName()}});
}
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleRateLimitNonHttp.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleRateLimitNonHttp.getName()}});
}
}
}
LOG.debug(String.format("Rate-limit rules successfully removed from load balancer '%s'.", virtualServerName));
}
private void removeRateLimitRulesFromVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
removeRateLimitRulesFromVirtualServer(serviceStubs, vsName);
}
}
private void attachXFFRuleToVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
if (serviceStubs.getVirtualServerBinding().getProtocol(new String[]{virtualServerName})[0].equals(VirtualServerProtocol.http)) {
LOG.debug(String.format("Attaching the XFF rule and enabling it on load balancer '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{ZxtmAdapterImpl.ruleXForwardedFor}});
LOG.debug(String.format("XFF rule successfully enabled on load balancer '%s'.", virtualServerName));
}
}
private void attachXFPORTRuleToVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
if (serviceStubs.getVirtualServerBinding().getProtocol(new String[]{virtualServerName})[0].equals(VirtualServerProtocol.http)) {
LOG.debug(String.format("Attaching the XFPORT rule and enabling it on load balancer '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{ZxtmAdapterImpl.ruleXForwardedPort}});
LOG.debug(String.format("XFPORT rule successfully enabled on load balancer '%s'.", virtualServerName));
}
}
private void attachXFPRuleToVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
if (serviceStubs.getVirtualServerBinding().getProtocol(new String[]{virtualServerName})[0].equals(VirtualServerProtocol.http)) {
LOG.debug(String.format("Attaching the XFP rule and enabling it on load balancer '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{ZxtmAdapterImpl.ruleXForwardedProto}});
LOG.debug(String.format("XFP rule successfully enabled on load balancer '%s'.", virtualServerName));
}
}
private void attachForceHttpsRedirectRuleToVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
if (serviceStubs.getVirtualServerBinding().getProtocol(new String[]{virtualServerName})[0].equals(VirtualServerProtocol.http)) {
LOG.debug(String.format("Attaching the Https Redirect rule and enabling it on load balancer '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{ZxtmAdapterImpl.ruleForceHttpsRedirect}});
LOG.debug(String.format("Https Redirect rule successfully enabled on load balancer '%s'.", virtualServerName));
}
}
private void attachXFFRuleToVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
attachXFFRuleToVirtualServer(serviceStubs, vsName);
}
}
private void attachXFPRuleToVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
attachXFPRuleToVirtualServer(serviceStubs, vsName);
}
}
private void attachXFPORTRuleToVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
attachXFPORTRuleToVirtualServer(serviceStubs, vsName);
}
}
private void attachXFFRuleToVirtualServerForced(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Attaching the XFF rule and enabling it on load balancer '%s'...", virtualServerName));
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{ZxtmAdapterImpl.ruleXForwardedFor}});
LOG.debug(String.format("XFF rule successfully enabled on load balancer '%s'.", virtualServerName));
}
private void removeXFFRuleFromVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Removing the XFF rule from load balancer '%s'...", virtualServerName));
VirtualServerRule[][] virtualServerRules = serviceStubs.getVirtualServerBinding().getRules(new String[]{virtualServerName});
if (virtualServerRules.length > 0) {
for (VirtualServerRule virtualServerRule : virtualServerRules[0]) {
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleXForwardedFor.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleXForwardedFor.getName()}});
}
}
}
LOG.debug(String.format("XFF rule successfully removed from load balancer '%s'.", virtualServerName));
}
private void removeXFPRuleFromVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Removing the XFP rule from load balancer '%s'...", virtualServerName));
VirtualServerRule[][] virtualServerRules = serviceStubs.getVirtualServerBinding().getRules(new String[]{virtualServerName});
if (virtualServerRules.length > 0) {
for (VirtualServerRule virtualServerRule : virtualServerRules[0]) {
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleXForwardedProto.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleXForwardedProto.getName()}});
}
}
}
LOG.debug(String.format("XFP rule successfully removed from load balancer '%s'.", virtualServerName));
}
private void removeXFPORTRuleFromVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Removing the XFPORT rule from load balancer '%s'...", virtualServerName));
VirtualServerRule[][] virtualServerRules = serviceStubs.getVirtualServerBinding().getRules(new String[]{virtualServerName});
if (virtualServerRules.length > 0) {
for (VirtualServerRule virtualServerRule : virtualServerRules[0]) {
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleXForwardedPort.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleXForwardedPort.getName()}});
}
}
}
LOG.debug(String.format("XFPORT rule successfully removed from load balancer '%s'.", virtualServerName));
}
private void removeForceHttpsRedirectRuleFromVirtualServer(ZxtmServiceStubs serviceStubs, String virtualServerName) throws RemoteException {
LOG.debug(String.format("Removing the Https Redirect rule from load balancer '%s'...", virtualServerName));
VirtualServerRule[][] virtualServerRules = serviceStubs.getVirtualServerBinding().getRules(new String[]{virtualServerName});
if (virtualServerRules.length > 0) {
for (VirtualServerRule virtualServerRule : virtualServerRules[0]) {
if (virtualServerRule.getName().equals(ZxtmAdapterImpl.ruleForceHttpsRedirect.getName())) {
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{ZxtmAdapterImpl.ruleForceHttpsRedirect.getName()}});
}
}
}
LOG.debug(String.format("Https Redirect rule successfully removed from load balancer '%s'.", virtualServerName));
}
private void removeXFFRuleFromVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
removeXFFRuleFromVirtualServer(serviceStubs, vsName);
}
}
private void removeXFPRuleFromVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
removeXFPRuleFromVirtualServer(serviceStubs, vsName);
}
}
private void removeXFPORTRuleFromVirtualServers(ZxtmServiceStubs serviceStubs, String[] virtualServerNames) throws RemoteException {
for (String vsName : virtualServerNames) {
removeXFPORTRuleFromVirtualServer(serviceStubs, vsName);
}
}
@Override
public void updateSslTermination(LoadBalancerEndpointConfiguration conf, LoadBalancer loadBalancer, ZeusSslTermination zeusSslTermination) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String virtualServerName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
final String virtualServerNameNonSecure = ZxtmNameBuilder.genVSName(loadBalancer);
String userKey = zeusSslTermination.getSslTermination().getPrivatekey();
String userCrt = zeusSslTermination.getSslTermination().getCertificate();
String imdCrt = zeusSslTermination.getSslTermination().getIntermediateCertificate();
ZeusCrtFile zeusCrtFile = zeusUtil.buildZeusCrtFileLbassValidation(userKey, userCrt, imdCrt);
if (zeusCrtFile.hasFatalErrors()) {
String fmt = "ZeusCrtFile generation Failure: %s";
String errors = StringUtils.joinString(zeusCrtFile.getFatalErrorList(), ",");
String msg = String.format(fmt, errors);
throw new InsufficientRequestException(msg);
}
ZxtmServiceStubs serviceStubs = getServiceStubs(conf);
VirtualServerBindingStub virtualServerService = serviceStubs.getVirtualServerBinding();
CatalogSSLCertificatesBindingStub certificateCatalogService = serviceStubs.getZxtmCatalogSSLCertificatesBinding();
try {
LOG.info(String.format("Creating ssl termination load balancer %s in zeus... ", virtualServerName));
createSecureVirtualServer(conf, loadBalancer);
} catch (Exception af) {
if (af instanceof ObjectAlreadyExists) {
LOG.warn(String.format("Secure virtual server '%s' already exists, ignoring....", virtualServerName));
}
}
if (!virtualServerService.getPort(new String[]{virtualServerName})[0].equals(zeusSslTermination.getSslTermination().getSecurePort())) {
LOG.info(String.format("Updating secure servers port for ssl termination load balancer %s in zeus...", virtualServerName));
updatePort(conf, virtualServerName, zeusSslTermination.getSslTermination().getSecurePort());
LOG.debug(String.format("Successfully updated secure servers port for ssl termination load balancer %s in zeus...", virtualServerName));
}
try {
if (zeusSslTermination.getCertIntermediateCert() != null) {
if (certificateCatalogService.getCertificateInfo(new String[]{virtualServerName}) != null) {
LOG.info(String.format("Certificate already exists, removing it for loadbalancer: %s", loadBalancer.getId()));
enableDisableSslTermination(conf, loadBalancer, false);
certificateCatalogService.deleteCertificate(new String[]{virtualServerName});
LOG.debug(String.format("Removed existing certificate for loadbalancer: %s", loadBalancer.getId()));
}
}
} catch (ObjectDoesNotExist odne) {
LOG.debug(String.format("The certificate does not exist, ignoring... loadbalancer: %s", loadBalancer.getId()));
}
try {
if (zeusSslTermination.getCertIntermediateCert() != null) {
LOG.info(String.format("Importing certificate for load balancer: %s", loadBalancer.getId()));
CertificateFiles certificateFiles = new CertificateFiles();
String privKey = zeusCrtFile.getPrivate_key();
String pubCrt = zeusCrtFile.getPublic_cert();
certificateFiles.setPrivate_key(privKey);
certificateFiles.setPublic_cert(pubCrt);
certificateCatalogService.importCertificate(new String[]{virtualServerName}, new CertificateFiles[]{certificateFiles});
LOG.debug(String.format("Successfully imported certificate for load balancer: %s", loadBalancer.getId()));
}
LOG.info(String.format("Attaching certificate and key, load balancer: %s ", loadBalancer.getId()));
virtualServerService.setSSLCertificate(new String[]{virtualServerName}, new String[]{virtualServerName});
LOG.debug(String.format("Succesfullly attached certificate and key for load balancer: %s", loadBalancer.getId()));
LOG.info(String.format("Ssl termination virtual server will be enabled:'%s' for load balancer: %s", zeusSslTermination.getSslTermination().isEnabled(), loadBalancer.getId()));
enableDisableSslTermination(conf, loadBalancer, zeusSslTermination.getSslTermination().isEnabled());
LOG.debug(String.format("Successfully enabled:'%s' load balancer: %s ssl termination", zeusSslTermination.getSslTermination().isEnabled(), loadBalancer.getId()));
boolean isRedirectServer = loadBalancer.isHttpsRedirect() != null && loadBalancer.isHttpsRedirect() == true;
if (!isRedirectServer) {
LOG.info(String.format("Non-secure virtual server will be enabled:'%s' load balancer: %s", zeusSslTermination.getSslTermination().isEnabled(), loadBalancer.getId()));
suspendUnsuspendVirtualServer(conf, virtualServerNameNonSecure, zeusSslTermination.getSslTermination().isSecureTrafficOnly());
LOG.debug(String.format("Successfully enabled:'%s' non-secure server for load balancer: %s", zeusSslTermination.getSslTermination().isEnabled(), loadBalancer.getId()));
}
} catch (AxisFault af) {
LOG.error("there was a error setting ssl termination in zxtm adapter for load balancer " + loadBalancer.getId());
//TODO: handle errors better...
throw new ZxtmRollBackException("there was a error setting ssl termination in zxtm adapter for load balancer " + loadBalancer.getId(), af);
}
}
@Override
public void removeSslTermination(LoadBalancerEndpointConfiguration conf, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
String virtualServerName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
String virtualServerNameNonSecure = ZxtmNameBuilder.genVSName(loadBalancer);
ZxtmServiceStubs serviceStubs = getServiceStubs(conf);
try {
//Detach and remove ssl termination (shadow server)
LOG.info(String.format("Detaching and disabling certificate for load balancer: '%s' virtual server name: %s", loadBalancer.getId(), virtualServerNameNonSecure));
enableDisableSslTermination(conf, loadBalancer, false);
try {
serviceStubs.getVirtualServerBinding().setSSLCertificate(new String[]{virtualServerName}, new String[]{""});
serviceStubs.getZxtmCatalogSSLCertificatesBinding().deleteCertificate(new String[]{virtualServerName});
} catch (ObjectDoesNotExist ex) {
LOG.info(String.format("Certificates or key does not exist for load balancer: %d ignoring... Exception: %s", loadBalancer.getId(), ex.getErrmsg()));
}
// Remove all certificates used for certificate mappings
for (CertificateMapping certificateMapping : loadBalancer.getCertificateMappings()) {
String certificateName = ZxtmNameBuilder.generateCertificateName(loadBalancer.getId(), loadBalancer.getAccountId(), certificateMapping.getId());
try {
LOG.info(String.format("Removing certificate '%s' for load balancer %d...", certificateName, loadBalancer.getId()));
serviceStubs.getZxtmCatalogSSLCertificatesBinding().deleteCertificate(new String[]{certificateName});
LOG.info(String.format("Successfully removed certificate '%s' for load balancer %d.", certificateName, loadBalancer.getId()));
} catch (ObjectDoesNotExist odne) {
LOG.info(String.format("Certificate '%s' does not exist for load balancer %d. Ignoring...", certificateName, loadBalancer.getId()));
}
}
try {
//Removing rateLimit from shadow server
LOG.info(String.format("Removing a rate limit from load balancer...'%s'...", loadBalancer.getId()));
removeRateLimitRulesFromVirtualServer(serviceStubs, virtualServerName);
serviceStubs.getZxtmRateCatalogService().deleteRate(new String[]{virtualServerName});
LOG.debug(String.format("Rules detached and deleted from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
} catch (ObjectDoesNotExist e) {
LOG.warn(String.format("There was an warning removing rate limit from the shadow server as it does not exist for load balancer: '%s' ", loadBalancer.getId()));
} catch (ObjectInUse e) {
LOG.warn(String.format("There was an warning removing rate limit from the shadow server as it is already in use for load balancer: '%s' ", loadBalancer.getId()));
} catch (RemoteException af) {
LOG.error(String.format("There was an unexpected exception while removing the secure virtual servers ratelimit for virtual server: %s", virtualServerName));
}
//Removing connectionThrottle from shadow server
LOG.info(String.format("Removing connectionThrottle from load balancer...'%s'...", loadBalancer.getId()));
zeroOutConnectionThrottleConfig(conf, loadBalancer);
updateConnectionThrottle(conf, loadBalancer, virtualServerName);
LOG.debug(String.format("Remove connectionThrottle from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
//Removing connectionLogging from shadow server
LOG.info(String.format("Removing connectionLogging from load balancer...'%s'...", loadBalancer.getId()));
loadBalancer.setConnectionLogging(false);
updateConnectionLogging(conf, loadBalancer, virtualServerName);
LOG.debug(String.format("Remove connectionLogging from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
//Removing accessList from shadow server
LOG.info(String.format("Removing accessList from load balancer...'%s'...", loadBalancer.getId()));
deleteAccessList(conf, virtualServerName);
LOG.debug(String.format("Remove accessList from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
//Removing error file from shadow server
LOG.info(String.format("Removing error file from load balancer...'%s' for ssl termination...", loadBalancer.getId()));
deleteErrorFile(conf, virtualServerName);
LOG.debug(String.format("Remove error file from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
//Removing protectionCatalog from shadow server
LOG.info(String.format("Removing protection catalog from load balancer...'%s'...", loadBalancer.getId()));
deleteProtectionCatalog(serviceStubs, virtualServerName);
LOG.debug(String.format("Removed protection catalog from the ssl terminated virtual server, for loadbalancer: '%s' ", loadBalancer.getId()));
//Removing the secure VS
try {
LOG.info(String.format(String.format("Removing the secure virtual server: %s", virtualServerName)));
deleteVirtualServer(serviceStubs, virtualServerName);
LOG.debug(String.format(String.format("Successfully removed the secure virtual server: %s", virtualServerName)));
} catch (ObjectDoesNotExist dne) {
//Only happens when deleteLoadBalancer calls us
LOG.info(String.format("Virtual server %s was not found for %s removeSslTermination, ignoring...", virtualServerName, virtualServerNameNonSecure));
}
//Returning the non-secure VS to default state if HTTPS Redirect was turned on
if (loadBalancer.isHttpsRedirect() != null && loadBalancer.isHttpsRedirect() == true) {
restoreVirtualServerFromHttpsRedirect(loadBalancer, serviceStubs);
}
//Un-suspending non-secure VS
try {
LOG.info("Suspending/disabling non-secure virtual server for load balancer: " + loadBalancer.getId());
suspendUnsuspendVirtualServer(conf, virtualServerNameNonSecure, false);
LOG.debug("Successfully suspended/disabled non-secure virtual server for load balancer: " + loadBalancer.getId());
} catch (ObjectDoesNotExist dne) {
//Only happens when deleteLoadBalancer calls us
LOG.info(String.format("Virtual server %s was not found for %s to suspend or enable, ignoring...", virtualServerName, virtualServerNameNonSecure));
}
} catch (Exception af) {
LOG.error(String.format("there was a error removing ssl termination in zxtm adapter for load balancer: '%s'", loadBalancer.getId()));
throw new ZxtmRollBackException("There was an error removing ssl termination from load balancer: " + loadBalancer.getId(), af);
}
}
@Override
public void enableDisableSslTermination(LoadBalancerEndpointConfiguration conf, LoadBalancer loadBalancer, boolean isSslTermination) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String virtualServerName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
ZxtmServiceStubs serviceStubs = getServiceStubs(conf);
try {
serviceStubs.getVirtualServerBinding().setSSLDecrypt(new String[]{virtualServerName}, new boolean[]{isSslTermination});
boolean[] isVSEnabled;
if (loadBalancer.getSslTermination() != null) {
isVSEnabled = new boolean[]{loadBalancer.getSslTermination().isEnabled()};
} else {
isVSEnabled = new boolean[]{false};
}
serviceStubs.getVirtualServerBinding().setEnabled(new String[]{virtualServerName}, isVSEnabled);
} catch (RemoteException af) {
String msg = String.format("There was a error enabling/disabling ssl termination for loadbalancer: %d", loadBalancer.getId());
LOG.error(msg);
throw new ZxtmRollBackException(msg, af);
}
}
// upload the file then set the Errorpage.
@Override
public void setErrorFile(LoadBalancerEndpointConfiguration conf, LoadBalancer loadbalancer, String content) throws RemoteException, InsufficientRequestException {
Integer lbId = loadbalancer.getId();
Integer accountId = loadbalancer.getAccountId();
ZxtmServiceStubs serviceStubs = getServiceStubs(conf);
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
setErrorFile(conf, vsName, content);
}
}
public void setErrorFile(LoadBalancerEndpointConfiguration conf, String vsName, String content) throws RemoteException {
String[] vsNames = new String[1];
String[] errorFiles = new String[1];
ZxtmServiceStubs serviceStubs = getServiceStubs(conf);
ConfExtraBindingStub extraService = serviceStubs.getZxtmConfExtraBinding();
VirtualServerBindingStub virtualServerService = serviceStubs.getVirtualServerBinding();
String errorFileName = getErrorFileName(vsName);
try {
LOG.debug(String.format("Attempting to upload the error file: %s for: %s", errorFileName, vsName));
extraService.uploadFile(errorFileName, content.getBytes());
LOG.info(String.format("Successfully uploaded the error file: %s for: %s...", errorFileName, vsName));
vsNames[0] = String.format("%s", vsName);
errorFiles[0] = errorFileName;
LOG.debug("Attempting to set the error file...");
virtualServerService.setErrorFile(vsNames, errorFiles);
LOG.info(String.format("Successfully set the error file for: %s...", vsName));
} catch (InvalidInput ip) {
//Couldn't find a custom 'default' error file...
LOG.error(String.format("The Error file: %s could not be set for: %s", errorFileName, vsName));
virtualServerService.setErrorFile(vsNames, new String[]{"Default"});
}
}
@Override
public void removeAndSetDefaultErrorFile(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws InsufficientRequestException, RemoteException {
deleteErrorFile(config, loadBalancer);
setDefaultErrorFile(config, loadBalancer);
}
@Override
public void uploadDefaultErrorFile(LoadBalancerEndpointConfiguration config, String content) throws InsufficientRequestException, RemoteException {
ZxtmServiceStubs serviceStubs = null;
serviceStubs = getServiceStubs(config);
ConfExtraBindingStub extraService = null;
LOG.debug("Attempting to upload the default error file...");
extraService = serviceStubs.getZxtmConfExtraBinding();
if (extraService != null) {
extraService.uploadFile(Constants.DEFAULT_ERRORFILE, content.getBytes());
LOG.info("Successfully uploaded the default error file...");
}
}
@Override
public void setDefaultErrorFile(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws InsufficientRequestException, RemoteException {
Integer lbId = loadBalancer.getId();
Integer accountId = loadBalancer.getAccountId();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
setDefaultErrorFile(config, vsName);
}
}
public void setDefaultErrorFile(LoadBalancerEndpointConfiguration config, String vsName) throws InsufficientRequestException, RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
LOG.debug(String.format("Attempting to set the default error file for: %s", vsName));
//TODO: uncomment when zeus performance issues are resolved... (VERSION 1) TK-12805
try {
// serviceStubs.getVirtualServerBinding().setErrorFile(new String[]{vsName}, new String[]{Constants.DEFAULT_ERRORFILE});
serviceStubs.getVirtualServerBinding().setErrorFile(new String[]{vsName}, new String[]{"Default"});
LOG.info(String.format("Successfully set the default error file for: %s", vsName));
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Virtual server %s does not exist, ignoring...", vsName));
}
}
@Override
public void deleteErrorFile(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws AxisFault, InsufficientRequestException {
Integer lbId = loadBalancer.getId();
Integer accountId = loadBalancer.getAccountId();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
try {
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
deleteErrorFile(config, vsName);
}
} catch (RemoteException e) {
//TODO what should we do here?
}
}
public void deleteErrorFile(LoadBalancerEndpointConfiguration config, String vsName) throws AxisFault, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String fileToDelete = getErrorFileName(vsName);
try {
LOG.debug(String.format("Attempting to delete a custom error file for: %s", vsName));
serviceStubs.getVirtualServerBinding().setErrorFile(new String[]{vsName}, new String[]{"Default"});
serviceStubs.getZxtmConfExtraBinding().deleteFile(new String[]{fileToDelete});
LOG.info(String.format("Successfully deleted a custom error file for: %s", vsName));
} catch (RemoteException e) {
if (e instanceof ObjectDoesNotExist) {
LOG.warn(String.format("Cannot delete custom error page as, %s, it does not exist. Ignoring...", fileToDelete));
}
} catch (Exception ex) {
LOG.error(String.format("There was a unexpected error deleting the error file for: %s Exception: %s", vsName, ex.getMessage()));
}
}
@Override
public void deleteRateLimit(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException {
deleteRateLimit(config, ZxtmNameBuilder.genVSName(loadBalancer));
if (loadBalancer.hasSsl()) {
deleteRateLimit(config, ZxtmNameBuilder.genSslVSName(loadBalancer));
}
}
public void deleteRateLimit(LoadBalancerEndpointConfiguration config, String vsName) throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
removeRateLimitRulesFromVirtualServers(serviceStubs, new String[]{vsName});
LOG.debug(String.format("Removing a rate limit from load balancer...'%s'...", vsName));
serviceStubs.getZxtmRateCatalogService().deleteRate(new String[]{vsName});
LOG.info("Successfully removed a rate limit from the rate limit pool.");
LOG.info("Rules detached from the VS, delete rate limit sucessfully completed.");
} catch (RemoteException e) {
if (e instanceof ObjectDoesNotExist) {
LOG.warn(String.format("Cannot delete rate limit for virtual server '%s' as it does not exist. Ignoring...", vsName));
}
if (e instanceof ObjectInUse) {
LOG.warn(String.format("Cannot delete rate limit for virtual server '%s' as it is in use. Ignoring...", vsName));
}
}
}
@Override
public void updateRateLimit(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, RateLimit rateLimit) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
updateRateLimit(config, ZxtmNameBuilder.genVSName(loadBalancer), rateLimit);
if (loadBalancer.hasSsl()) {
updateRateLimit(config, ZxtmNameBuilder.genSslVSName(loadBalancer), rateLimit);
}
}
@Override
public void updateTimeout(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(loadBalancer.getId(), loadBalancer.getAccountId());
if (loadBalancer.getTimeout() != null) {
serviceStubs.getPoolBinding().setMaxReplyTime(new String[]{poolName}, new UnsignedInt[]{new UnsignedInt(loadBalancer.getTimeout())});
}
}
public void updateRateLimit(LoadBalancerEndpointConfiguration config, String vsName, RateLimit rateLimit) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
try {
LOG.debug(String.format("Removing the current rate limit from load balancer...'%s'...", vsName));
deleteRateLimit(config, vsName);
LOG.info("Successfully removed a rate limit from the rate limit pool.");
LOG.debug("Attaching new rate limit to the virtual server.");
setRateLimit(config, vsName, rateLimit);
LOG.info("Rules attached to the VS, update rate limit sucessfully completed.");
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot update rate limit for virtual server '%s' as it does not exist.", vsName));
}
throw new ZxtmRollBackException("Update rate limit request canceled.", e);
}
}
@Override
public void changeHostForLoadBalancer(LoadBalancerEndpointConfiguration config, LoadBalancer lb, Host newHost) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String trafficManagerName = newHost == null ? config.getTrafficManagerName() : newHost.getTrafficManagerName();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
List<String> tManagersList = config.getFailoverTrafficManagerNames();
tManagersList.add(trafficManagerName);
String[] allTrafficManagers = tManagersList.toArray(new String[config.getFailoverTrafficManagerNames().size()]);
// Redefine Traffic IP Groups for new HOST
for (LoadBalancerJoinVip loadBalancerJoinVip : lb.getLoadBalancerJoinVipSet()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip.getVirtualIp());
serviceStubs.getTrafficIpGroupBinding().setTrafficManager(new String[]{trafficIpGroupName}, new String[][]{allTrafficManagers});
}
for (LoadBalancerJoinVip6 loadBalancerJoinVip6 : lb.getLoadBalancerJoinVip6Set()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip6.getVirtualIp());
serviceStubs.getTrafficIpGroupBinding().setTrafficManager(new String[]{trafficIpGroupName}, new String[][]{allTrafficManagers});
}
}
@Override
public void setNodes(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
Integer lbId = lb.getId();
Integer accountId = lb.getAccountId();
Set<Node> nodes = lb.getNodes();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String rollBackMessage = "Set nodes request canceled.";
final String[][] enabledNodesBackup;
final String[][] disabledNodesBackup;
final String[][] drainingNodesBackup;
try {
LOG.debug(String.format("Backing up nodes for existing pool '%s'", poolName));
enabledNodesBackup = serviceStubs.getPoolBinding().getNodes(new String[]{poolName});
disabledNodesBackup = serviceStubs.getPoolBinding().getDisabledNodes(new String[]{poolName});
drainingNodesBackup = serviceStubs.getPoolBinding().getDrainingNodes(new String[]{poolName});
LOG.debug(String.format("Backup for existing pool '%s' created.", poolName));
LOG.debug(String.format("Setting nodes for existing pool '%s'", poolName));
serviceStubs.getPoolBinding().setNodes(new String[]{poolName}, NodeHelper.getIpAddressesFromNodes(nodes));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Cannot set nodes for pool '%s' as it does not exist.", poolName), e);
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
try {
setDisabledNodes(config, poolName, getNodesWithCondition(nodes, NodeCondition.DISABLED));
setDrainingNodes(config, poolName, getNodesWithCondition(nodes, NodeCondition.DRAINING));
setNodeWeights(config, lbId, accountId, nodes);
setNodesPriorities(config, poolName, lb);
} catch (Exception e) {
if (e instanceof InvalidInput) {
LOG.error(String.format("Error setting node conditions for pool '%s'. All nodes cannot be disabled.", poolName), e);
}
LOG.debug(String.format("Restoring pool '%s' with backup...", poolName));
serviceStubs.getPoolBinding().setNodes(new String[]{poolName}, enabledNodesBackup);
serviceStubs.getPoolBinding().setDisabledNodes(new String[]{poolName}, disabledNodesBackup);
serviceStubs.getPoolBinding().setDrainingNodes(new String[]{poolName}, drainingNodesBackup);
LOG.debug(String.format("Backup successfully restored for pool '%s'.", poolName));
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
private void setDisabledNodes(LoadBalancerEndpointConfiguration config, String poolName, List<Node> nodesToDisable) throws RemoteException {
if (nodesToDisable == null || nodesToDisable.isEmpty()) {
return;
}
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
LOG.debug(String.format("Setting disabled nodes for pool '%s'", poolName));
serviceStubs.getPoolBinding().setDisabledNodes(new String[]{poolName}, NodeHelper.getIpAddressesFromNodes(nodesToDisable));
LOG.debug(String.format("Successfully set disabled nodes for pool '%s'", poolName));
}
private void setDrainingNodes(LoadBalancerEndpointConfiguration config, String poolName, List<Node> nodesToDrain) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String[][] currentDrainingNodes = serviceStubs.getPoolBinding().getDrainingNodes(new String[]{poolName});
if (nodesToDrain != null && !nodesToDrain.isEmpty()) {
LOG.debug(String.format("Setting draining nodes for pool '%s'", poolName));
serviceStubs.getPoolBinding().setDrainingNodes(new String[]{poolName}, NodeHelper.getIpAddressesFromNodes(nodesToDrain));
LOG.debug(String.format("Successfully set draining nodes for pool '%s'", poolName));
} else if (currentDrainingNodes[0].length > 0) {
LOG.debug(String.format("Removing draining nodes for pool '%s'", poolName));
serviceStubs.getPoolBinding().removeDrainingNodes(new String[]{poolName}, currentDrainingNodes);
LOG.debug(String.format("Successfully removed draining nodes for pool '%s'", poolName));
}
}
@Override
public void removeNodes(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, Collection<Node> nodes)
throws AxisFault, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String rollBackMessage = "Remove node request canceled.";
try {
String[][] ipAndPorts = NodeHelper.getIpAddressesFromNodes(nodes);
serviceStubs.getPoolBinding().removeNodes(new String[]{poolName}, ipAndPorts);
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Node pool '%s' for nodes %s does not exist.", poolName, NodeHelper.getNodeIdsStr(nodes)));
LOG.warn(StringConverter.getExtendedStackTrace(odne));
} catch (Exception e) {
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
@Override
public void removeNode(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, String ipAddress, Integer port)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String rollBackMessage = "Remove node request canceled.";
try {
serviceStubs.getPoolBinding().removeNodes(new String[]{poolName}, NodeHelper.buildNodeInfo(ipAddress, port));
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Node pool '%s' for node '%s:%d' does not exist.", poolName, ipAddress, port));
} catch (Exception e) {
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
@Override
public void setNodeWeights(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, Collection<Node> nodes)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
if (nodes == null || nodes.isEmpty()) return;
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String rollBackMessage = "Update node weights request canceled.";
try {
final PoolLoadBalancingAlgorithm[] loadBalancingAlgorithm = serviceStubs.getPoolBinding().getLoadBalancingAlgorithm(new String[]{poolName});
if (loadBalancingAlgorithm[0].equals(PoolLoadBalancingAlgorithm.wroundrobin) || loadBalancingAlgorithm[0].equals(PoolLoadBalancingAlgorithm.wconnections)) {
LOG.debug(String.format("Setting node weights for pool '%s'...", poolName));
serviceStubs.getPoolBinding().setNodesWeightings(new String[]{poolName}, buildPoolWeightingsDefinition(nodes));
LOG.info(String.format("Node weights successfully set for pool '%s'.", poolName));
}
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Node pool '%s' does not exist. Cannot update node weights", poolName), e);
}
if (e instanceof InvalidInput) {
LOG.error(String.format("Node weights are out of range for node pool '%s'. Cannot update node weights", poolName), e);
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
public void setSessionPersistence(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException
{
}
public void removeSessionPersistence(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException
{
}
@Override
public void setSessionPersistence(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId, SessionPersistence mode)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
boolean httpCookieClassConfigured = false;
boolean sourceIpClassConfigured = false;
boolean sslIdClassConfigured = false;
final String rollBackMessage = "Update session persistence request canceled.";
LOG.debug(String.format("Setting session persistence for node pool '%s'...", poolName));
String[] persistenceClasses = serviceStubs.getPersistenceBinding().getPersistenceNames();
// Iterate through all persistence classes to determine if the
// cookie and source IP class exist. If they exist, then it is
// assumed they are configured correctly.
if (persistenceClasses != null) {
for (String persistenceClass : persistenceClasses) {
if (persistenceClass.equals(HTTP_COOKIE)) {
httpCookieClassConfigured = true;
}
if (persistenceClass.equals(SOURCE_IP)) {
sourceIpClassConfigured = true;
}
if (persistenceClass.equals(SSL_ID)) {
sslIdClassConfigured = true;
}
}
}
// Create the HTTP cookie class if it is not yet configured.
if (!httpCookieClassConfigured) {
serviceStubs.getPersistenceBinding().addPersistence(new String[]{HTTP_COOKIE});
serviceStubs.getPersistenceBinding().setType(new String[]{HTTP_COOKIE}, new CatalogPersistenceType[]{CatalogPersistenceType.value4});
serviceStubs.getPersistenceBinding().setFailureMode(new String[]{HTTP_COOKIE}, new CatalogPersistenceFailureMode[]{CatalogPersistenceFailureMode.newnode});
}
// Create the source IP class if it is not yet configured.
if (!sourceIpClassConfigured) {
serviceStubs.getPersistenceBinding().addPersistence(new String[]{SOURCE_IP});
serviceStubs.getPersistenceBinding().setType(new String[]{SOURCE_IP}, new CatalogPersistenceType[]{CatalogPersistenceType.value1});
serviceStubs.getPersistenceBinding().setFailureMode(new String[]{SOURCE_IP}, new CatalogPersistenceFailureMode[]{CatalogPersistenceFailureMode.newnode});
}
// Create the SSL_ID class if it is not yet configured
if (!sslIdClassConfigured) {
serviceStubs.getPersistenceBinding().addPersistence(new String[]{SSL_ID});
serviceStubs.getPersistenceBinding().setType(new String[]{SSL_ID}, new CatalogPersistenceType[]{CatalogPersistenceType.value9});
serviceStubs.getPersistenceBinding().setFailureMode(new String[]{SSL_ID}, new CatalogPersistenceFailureMode[]{CatalogPersistenceFailureMode.newnode});
}
try {
// Set the session persistence mode for the pool.
serviceStubs.getPoolBinding().setPersistence(new String[]{poolName}, getPersistenceMode(mode));
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Node pool '%s' does not exist. Cannot update session persistence.", poolName));
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Session persistence successfully set for node pool '%s'.", poolName));
}
@Override
public void removeSessionPersistence(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String rollBackMessage = "Remove session persistence request canceled.";
try {
LOG.debug(String.format("Removing session persistence from node pool '%s'...", poolName));
serviceStubs.getPoolBinding().setPersistence(new String[]{poolName}, new String[]{""});
LOG.info(String.format("Session persistence successfully removed from node pool '%s'.", poolName));
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Node pool '%s' does not exist. No session persistence to remove.", poolName));
} catch (Exception e) {
throw new ZxtmRollBackException(rollBackMessage, e);
}
}
@Override
public void updateConnectionLogging(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Integer lbId = loadBalancer.getId();
Integer accountId = loadBalancer.getAccountId();
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
updateConnectionLogging(config, loadBalancer, vsName);
}
}
private void updateConnectionLogging(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, String virtualServerName)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
boolean isConnectionLogging = loadBalancer.isConnectionLogging();
LoadBalancerProtocol protocol = loadBalancer.getProtocol();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String rollBackMessage = "Update connection logging request canceled.";
if (isConnectionLogging) {
LOG.debug(String.format("ENABLING logging for virtual server '%s'...", virtualServerName));
} else {
LOG.debug(String.format("DISABLING logging for virtual server '%s'...", virtualServerName));
}
try {
if (isConnectionLogging) {
if (protocol != LoadBalancerProtocol.HTTP) {
serviceStubs.getVirtualServerBinding().setLogFormat(new String[]{virtualServerName}, new String[]{NON_HTTP_LOG_FORMAT});
} else if (protocol == LoadBalancerProtocol.HTTP) {
serviceStubs.getVirtualServerBinding().setLogFormat(new String[]{virtualServerName}, new String[]{HTTP_LOG_FORMAT});
}
serviceStubs.getVirtualServerBinding().setLogFilename(new String[]{virtualServerName}, new String[]{config.getLogFileLocation()});
}
serviceStubs.getVirtualServerBinding().setLogEnabled(new String[]{virtualServerName}, new boolean[]{isConnectionLogging});
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Virtual server '%s' does not exist. Cannot update connection logging.", virtualServerName));
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Successfully updated connection logging for virtual server '%s'...", virtualServerName));
}
@Override
public void updateContentCaching(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Integer lbId = loadBalancer.getId();
Integer accountId = loadBalancer.getAccountId();
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
updateContentCaching(config, loadBalancer, vsName);
}
}
private void updateContentCaching(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, String virtualServerName)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
boolean isContentCaching = false;
if (loadBalancer.isContentCaching() != null) {
isContentCaching = loadBalancer.isContentCaching();
}
LoadBalancerProtocol protocol = loadBalancer.getProtocol();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String rollBackMessage = "Update content caching request canceled.";
if (isContentCaching) {
LOG.debug(String.format("ENABLING content caching for virtual server '%s'...", virtualServerName));
} else {
LOG.debug(String.format("DISABLING content caching for virtual server '%s'...", virtualServerName));
}
try {
VirtualServerRule contentCachingRule = ZxtmAdapterImpl.ruleContentCaching;
if (isContentCaching) {
LOG.debug("Attach content caching rule and enable on the virtual server.");
if (protocol.equals(LoadBalancerProtocol.HTTP)) {
serviceStubs.getVirtualServerBinding().addRules(new String[]{virtualServerName}, new VirtualServerRule[][]{{contentCachingRule}});
serviceStubs.getVirtualServerBinding().setWebcacheEnabled(new String[]{virtualServerName}, new boolean[]{isContentCaching});
LOG.info("Rules attached to the VS, update content caching successfully completed.");
} else {
LOG.info("Content caching rule not set because loadbalancer protocol is not HTTP.");
serviceStubs.getVirtualServerBinding().setWebcacheEnabled(new String[]{virtualServerName}, new boolean[]{false});
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{contentCachingRule.getName()}});
}
} else {
LOG.info("Removing content caching rule from virtualserver: " + virtualServerName);
serviceStubs.getVirtualServerBinding().setWebcacheEnabled(new String[]{virtualServerName}, new boolean[]{false});
serviceStubs.getVirtualServerBinding().removeRules(new String[]{virtualServerName}, new String[][]{{contentCachingRule.getName()}});
}
} catch (ObjectDoesNotExist obdne) {
LOG.error("Virtual server not found, ignoring this request......" + obdne);
} catch (DeploymentError e) {
LOG.error("Error updating content caching..." + e);
throw new ZxtmRollBackException(rollBackMessage, e);
} catch (InvalidInput e) {
LOG.error("Content caching not found, ignoring..." + e);
} catch (RemoteException e) {
LOG.error("Error updating content caching..." + e);
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Successfully updated content caching for virtual server '%s'...", virtualServerName));
}
@Override
public void updateConnectionThrottle(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Integer lbId = loadBalancer.getId();
Integer accountId = loadBalancer.getAccountId();
String virtualServerName = ZxtmNameBuilder.genVSName(lbId, accountId);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(lbId, accountId);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
updateConnectionThrottle(config, loadBalancer, vsName);
}
}
private void updateConnectionThrottle(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, String virtualServerName) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ConnectionLimit throttle = loadBalancer.getConnectionLimit();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String protectionClassName = ZxtmNameBuilder.genVSName(loadBalancer);
String rollBackMessage = "Update connection throttle request canceled.";
addProtectionClass(config, protectionClassName);
try {
if (throttle != null) {
// This request is "non-negotiable" until Stingray can fix a bug that makes the remaining fields invalid.
serviceStubs.getProtectionBinding().setPerProcessConnectionCount(new String[]{protectionClassName}, new boolean[]{false});
if (throttle.getMinConnections() != null) {
// Set the minimum connections that will be allowed from any single IP before beginning to apply restrictions.
serviceStubs.getProtectionBinding().setMinConnections(new String[]{protectionClassName}, new UnsignedInt[]{new UnsignedInt(0)});
}
if (throttle.getRateInterval() != null) {
// Set the rate interval for the rates
serviceStubs.getProtectionBinding().setRateTimer(new String[]{protectionClassName}, new UnsignedInt[]{new UnsignedInt(1)});
}
//Odd issue in 9.5 where rateInterval must be set before max rate...
if (throttle.getMaxConnectionRate() != null) {
// Set the maximum connection rate + rate interval
serviceStubs.getProtectionBinding().setMaxConnectionRate(new String[]{protectionClassName}, new UnsignedInt[]{new UnsignedInt(0)});
}
if (throttle.getMaxConnections() != null) {
// Set the maximum connections permitted from a single IP address
serviceStubs.getProtectionBinding().setMax1Connections(new String[]{protectionClassName}, new UnsignedInt[]{new UnsignedInt(throttle.getMaxConnections())});
}
// We wont be using this, but it must be set to 0 as our default
serviceStubs.getProtectionBinding().setMax10Connections(new String[]{protectionClassName}, new UnsignedInt[]{new UnsignedInt(0)});
// Apply the service protection to the virtual server.
serviceStubs.getVirtualServerBinding().setProtection(new String[]{virtualServerName}, new String[]{protectionClassName});
}
} catch (Exception e) {
if (e instanceof ObjectDoesNotExist) {
LOG.error(String.format("Protection class '%s' does not exist. Cannot update connection throttling.", protectionClassName));
}
throw new ZxtmRollBackException(rollBackMessage, e);
}
LOG.info(String.format("Successfully updated connection throttle for virtual server '%s'.", virtualServerName));
}
@Override
public void deleteConnectionThrottle(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
deleteConnectionThrottle(config, loadBalancer, ZxtmNameBuilder.genVSName(loadBalancer));
}
public void deleteConnectionThrottle(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, String vsName)
throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
final String rollBackMessage = "Delete connection throttle request canceled.";
LOG.debug(String.format("Deleting connection throttle for loadbalancer '%s'...", vsName));
try {
zeroOutConnectionThrottleConfig(config, loadBalancer);
updateConnectionThrottle(config, loadBalancer);
LOG.info(String.format("Successfully zeroed out connection throttle settings for protection class '%s'.", vsName));
} catch (ZxtmRollBackException zre) {
throw new ZxtmRollBackException(rollBackMessage, zre);
}
LOG.info(String.format("Successfully deleted connection throttle for loadbalancer '%s'.", vsName));
}
private void zeroOutConnectionThrottleConfig(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
zeroOutConnectionThrottleConfig(config, loadBalancer, ZxtmNameBuilder.genVSName(loadBalancer));
if (loadBalancer.hasSsl()) {
zeroOutConnectionThrottleConfig(config, loadBalancer, ZxtmNameBuilder.genSslVSName(loadBalancer));
}
}
private void zeroOutConnectionThrottleConfig(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer, String vsName) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
LOG.debug(String.format("Zeroing out connection throttle settings for protection class '%s'.", vsName));
ConnectionLimit throttle = new ConnectionLimit();
throttle.setMaxConnectionRate(0);
throttle.setMaxConnections(0);
throttle.setMinConnections(0);
throttle.setRateInterval(1);
loadBalancer.setConnectionLimit(throttle);
}
@Override
public void updateHealthMonitor(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
int lbId = loadBalancer.getId();
int accountId = loadBalancer.getAccountId();
HealthMonitor healthMonitor = loadBalancer.getHealthMonitor();
final String poolName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String monitorName = poolName;
LOG.debug(String.format("Updating health monitor for node pool '%s'.", poolName));
addMonitorClass(config, monitorName);
// Set the properties on the monitor class that apply to all configurations.
serviceStubs.getMonitorBinding().setDelay(new String[]{monitorName}, new UnsignedInt[]{new UnsignedInt(healthMonitor.getDelay())});
serviceStubs.getMonitorBinding().setTimeout(new String[]{monitorName}, new UnsignedInt[]{new UnsignedInt(healthMonitor.getTimeout())});
serviceStubs.getMonitorBinding().setFailures(new String[]{monitorName}, new UnsignedInt[]{new UnsignedInt(healthMonitor.getAttemptsBeforeDeactivation())});
if (healthMonitor.getType().equals(HealthMonitorType.CONNECT)) {
serviceStubs.getMonitorBinding().setType(new String[]{monitorName}, new CatalogMonitorType[]{CatalogMonitorType.connect});
} else if (healthMonitor.getType().equals(HealthMonitorType.HTTP) || healthMonitor.getType().equals(HealthMonitorType.HTTPS)) {
serviceStubs.getMonitorBinding().setType(new String[]{monitorName}, new CatalogMonitorType[]{CatalogMonitorType.http});
serviceStubs.getMonitorBinding().setPath(new String[]{monitorName}, new String[]{healthMonitor.getPath()});
serviceStubs.getMonitorBinding().setStatusRegex(new String[]{monitorName}, new String[]{healthMonitor.getStatusRegex()});
serviceStubs.getMonitorBinding().setBodyRegex(new String[]{monitorName}, new String[]{healthMonitor.getBodyRegex()});
serviceStubs.getMonitorBinding().setHostHeader(new String[]{monitorName}, new String[]{healthMonitor.getHostHeader()});
if (healthMonitor.getType().equals(HealthMonitorType.HTTPS)) {
serviceStubs.getMonitorBinding().setUseSSL(new String[]{monitorName}, new boolean[]{true});
}
} else {
throw new InsufficientRequestException(String.format("Unsupported monitor type: %s", healthMonitor.getType().name()));
}
// Assign monitor to the node pool
String[][] monitors = new String[1][1];
monitors[0][0] = monitorName;
serviceStubs.getPoolBinding().setMonitors(new String[]{poolName}, monitors);
LOG.info(String.format("Health monitor successfully updated for node pool '%s'.", poolName));
}
@Override
public void removeHealthMonitor(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(loadBalancer);
final String monitorName = poolName;
String[][] monitors = new String[1][1];
monitors[0][0] = monitorName;
try {
LOG.debug(String.format("Removing health monitor for node pool '%s'...", poolName));
serviceStubs.getPoolBinding().removeMonitors(new String[]{monitorName}, new String[][]{new String[]{monitorName}});
LOG.info(String.format("Health monitor successfully removed for node pool '%s'.", poolName));
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Node pool '%s' does not exist. Ignoring...", poolName));
} catch (InvalidInput ii) {
LOG.warn(String.format("Health monitor for node pool '%s' does not exist. Ignoring.", poolName));
}
deleteMonitorClass(serviceStubs, monitorName);
}
private void deleteMonitorClass(ZxtmServiceStubs serviceStubs, String monitorName) throws RemoteException {
try {
LOG.debug(String.format("Removing monitor class '%s'...", monitorName));
serviceStubs.getMonitorBinding().deleteMonitors(new String[]{monitorName});
LOG.info(String.format("Monitor class '%s' successfully removed.", monitorName));
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Monitor class '%s' does not exist. Ignoring...", monitorName));
} catch (ObjectInUse oiu) {
LOG.error(String.format("Monitor class '%s' is currently in use. Cannot delete.", monitorName));
}
}
@Override
public void updateHalfClosed(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException {
String virtualServerName = ZxtmNameBuilder.genVSName(loadBalancer.getId(), loadBalancer.getAccountId());
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(loadBalancer.getId(), loadBalancer.getAccountId());
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(loadBalancer.getId(), loadBalancer.getAccountId());
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isRedirectServer && loadBalancer.hasSsl()) {
virtualServerName = virtualRedirectServerName;
} else if (isRedirectServer) {
try {
LOG.debug(String.format("Updating half close support for virtual server '%s': Value: '%s'...", virtualRedirectServerName, loadBalancer.isHalfClosed()));
serviceStubs.getVirtualServerBinding().setProxyClose(new String[]{virtualRedirectServerName}, new boolean[]{loadBalancer.isHalfClosed()});
} catch (Exception e) {
LOG.error("Could not update half close support for virtual server: " + virtualRedirectServerName);
}
}
try {
LOG.debug(String.format("Updating half close support for virtual server '%s': Value: '%s'...", virtualServerName, loadBalancer.isHalfClosed()));
serviceStubs.getVirtualServerBinding().setProxyClose(new String[]{virtualServerName}, new boolean[]{loadBalancer.isHalfClosed()});
} catch (Exception e) {
LOG.error("Could not update half close support for virtual server: " + virtualServerName);
}
if (loadBalancer.hasSsl()) {
try{
LOG.debug(String.format("Updating half close support for virtual server '%s': Value: '%s'...", virtualSecureServerName, loadBalancer.isHalfClosed()));
serviceStubs.getVirtualServerBinding().setProxyClose(new String[]{virtualSecureServerName}, new boolean[]{loadBalancer.isHalfClosed()});
} catch (Exception e) {
LOG.error("Could not update half close support for virtual server: " + virtualSecureServerName);
}
}
}
@Override
public void updateHttpsRedirect(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException {
String vsName = ZxtmNameBuilder.genVSName(loadBalancer);
String vsRedirectName = ZxtmNameBuilder.genRedirectVSName(loadBalancer);
try {
LOG.debug(String.format("Updating HTTPS Redirect for virtual server '%s': Value: '%s'...", vsName, loadBalancer.isHttpsRedirect()));
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
boolean redirectExists = Arrays.asList(serviceStubs.getVirtualServerBinding().getVirtualServerNames()).contains(vsRedirectName);
if (!redirectExists && loadBalancer.isHttpsRedirect() != null && loadBalancer.isHttpsRedirect()) {
if (loadBalancer.hasSsl() == true) {
repurposeVirtualServerForHttpsRedirect(loadBalancer, serviceStubs);
} else {
createRedirectVirtualServer(config,loadBalancer);
}
}
else if (redirectExists && loadBalancer.isHttpsRedirect() == null || !loadBalancer.isHttpsRedirect()) {
if (loadBalancer.hasSsl()) {
restoreVirtualServerFromHttpsRedirect(loadBalancer, serviceStubs);
} else {
deleteVirtualServer(serviceStubs, vsRedirectName);
}
}
} catch (Exception e) {
LOG.error("Could not update HTTPS Redirect for virtual server: " + vsName);
}
}
@Override
public void updateAccessList(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer)
throws RemoteException, InsufficientRequestException {
Collection<AccessList> accessListItems = loadBalancer.getAccessLists();
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String protectionClassName = ZxtmNameBuilder.genVSName(loadBalancer);
LOG.debug(String.format("Updating access list for protection class '%s'...", protectionClassName));
if (addProtectionClass(config, protectionClassName)) {
try {
zeroOutConnectionThrottleConfig(config, loadBalancer);
} catch (ZxtmRollBackException zre) {
LOG.warn("Could not zero out connection throttle settings. Continuing...", zre);
}
try {
updateConnectionThrottle(config, loadBalancer);
} catch (Exception e) {
LOG.warn("Could not update connection throttle settings. Continuing...", e);
}
}
LOG.info("Removing the old access list...");
//remove the current access list...
deleteAccessList(config, protectionClassName);
LOG.debug("adding the new access list...");
//add the new access list...
serviceStubs.getProtectionBinding().setAllowedAddresses(new String[]{protectionClassName}, buildAccessListItems(accessListItems, AccessListType.ALLOW));
serviceStubs.getProtectionBinding().setBannedAddresses(new String[]{protectionClassName}, buildAccessListItems(accessListItems, AccessListType.DENY));
//Not especially efficient, but we need to *make sure* we have added the protection class to all virtual servers (even though they probably are ok already)
String virtualServerName = ZxtmNameBuilder.genVSName(loadBalancer);
String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(loadBalancer);
String virtualRedirectServerName = ZxtmNameBuilder.genRedirectVSName(loadBalancer);
String[] vsNames;
boolean isSecureServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName);
boolean isRedirectServer = arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualRedirectServerName);
if (isSecureServer && isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualRedirectServerName;
vsNames[1] = virtualSecureServerName;
} else if (isSecureServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualSecureServerName;
} else if (isRedirectServer) {
vsNames = new String[2];
vsNames[0] = virtualServerName;
vsNames[1] = virtualRedirectServerName;
} else {
vsNames = new String[1];
vsNames[0] = virtualServerName;
}
for (String vsName : vsNames) {
// Apply the service protection to the virtual server.
serviceStubs.getVirtualServerBinding().setProtection(new String[]{vsName}, new String[]{protectionClassName});
}
LOG.info(String.format("Successfully updated access list for protection class '%s'...", protectionClassName));
}
@Override
public void deleteAccessList(LoadBalancerEndpointConfiguration config, Integer lbId, Integer accountId)
throws RemoteException, InsufficientRequestException {
final String protectionClassName = ZxtmNameBuilder.genVSName(lbId, accountId);
final String secureProtectionClassName = ZxtmNameBuilder.genSslVSName(lbId, accountId);
deleteAccessList(config, protectionClassName);
deleteAccessList(config, secureProtectionClassName);
}
@Override
public void deleteAccessList(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException {
}
private void deleteAccessList(LoadBalancerEndpointConfiguration config, String protectionClassName)
throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
String[][] allowList = serviceStubs.getProtectionBinding().getAllowedAddresses(new String[]{protectionClassName});
String[][] bannedList = serviceStubs.getProtectionBinding().getBannedAddresses(new String[]{protectionClassName});
serviceStubs.getProtectionBinding().removeAllowedAddresses(new String[]{protectionClassName}, allowList);
serviceStubs.getProtectionBinding().removeBannedAddresses(new String[]{protectionClassName}, bannedList);
//Shouldnt delete this until server is going away, connection throttle needs it, and removing it before theres a connection throttle means
//updateAccessListFails... should delete when removing the virtual server leave the protectionClass in place until then...
// serviceStubs.getProtectionBinding().deleteProtection(new String[]{poolName});
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Protection class '%s' already deleted.", protectionClassName));
} catch (ObjectInUse oiu) {
LOG.warn(String.format("Protection class '%s' is currently in use. Cannot delete.", protectionClassName));
}
}
@Override
public void suspendLoadBalancer(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lb.getId(), lb.getAccountId());
final String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lb.getId(), lb.getAccountId());
String[] poolNames;
boolean[] isEnabled;
if (arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName)) {
poolNames = new String[]{poolName, virtualSecureServerName};
isEnabled = new boolean[]{false, false};
} else {
poolNames = new String[]{poolName};
isEnabled = new boolean[]{false};
}
// Disable the virtual server
serviceStubs.getVirtualServerBinding().setEnabled(poolNames, isEnabled);
// Disable the traffic ip groups
LOG.info("grabbing all tigs related to VS..." + poolName);
for (LoadBalancerJoinVip loadBalancerJoinVip : lb.getLoadBalancerJoinVipSet()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip.getVirtualIp());
LOG.info("disabling tig " + trafficIpGroupName + " related to vs: " + poolName);
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroupName}, new boolean[]{false});
LOG.info("Succesfully disabled tig " + trafficIpGroupName + " on VS: " + poolName);
}
for (LoadBalancerJoinVip6 loadBalancerJoinVip6 : lb.getLoadBalancerJoinVip6Set()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip6.getVirtualIp());
LOG.info("disabling tig " + trafficIpGroupName + " related to vs: " + poolName);
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroupName}, new boolean[]{false});
LOG.info("Succesfully disabled tig " + trafficIpGroupName + " on VS: " + poolName);
}
}
@Override
public void removeSuspension(LoadBalancerEndpointConfiguration config, LoadBalancer lb)
throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(lb.getId(), lb.getAccountId());
final String virtualSecureServerName = ZxtmNameBuilder.genSslVSName(lb.getId(), lb.getAccountId());
String[] poolNames;
boolean[] isEnabled;
if (arrayElementSearch(serviceStubs.getVirtualServerBinding().getVirtualServerNames(), virtualSecureServerName)) {
poolNames = new String[]{poolName, ZxtmNameBuilder.genSslVSName(lb.getId(), lb.getAccountId())};
isEnabled = new boolean[]{true, true};
} else {
poolNames = new String[]{poolName};
isEnabled = new boolean[]{true};
}
// Disable the traffic ip groups
LOG.info("grabbing all tigs related to VS..." + poolName);
for (LoadBalancerJoinVip loadBalancerJoinVip : lb.getLoadBalancerJoinVipSet()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip.getVirtualIp());
LOG.info("enabling tig " + trafficIpGroupName + " related to vs: " + poolName);
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroupName}, new boolean[]{true});
LOG.info("Succesfully enabled tig " + trafficIpGroupName + " on VS: " + poolName);
}
for (LoadBalancerJoinVip6 loadBalancerJoinVip6 : lb.getLoadBalancerJoinVip6Set()) {
String trafficIpGroupName = ZxtmNameBuilder.generateTrafficIpGroupName(lb, loadBalancerJoinVip6.getVirtualIp());
LOG.info("enabling tig " + trafficIpGroupName + " related to vs: " + poolName);
serviceStubs.getTrafficIpGroupBinding().setEnabled(new String[]{trafficIpGroupName}, new boolean[]{true});
LOG.info("Succesfully enabled tig " + trafficIpGroupName + " on VS: " + poolName);
}
// Enable the virtual server
serviceStubs.getVirtualServerBinding().setEnabled(poolNames, isEnabled);
}
@Override
public void createHostBackup(LoadBalancerEndpointConfiguration config, String backupName) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
serviceStubs.getSystemBackupsBinding().createBackup(backupName, null);
}
@Override
public void deleteHostBackup(LoadBalancerEndpointConfiguration config, String backupName) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
serviceStubs.getSystemBackupsBinding().deleteBackups(new String[]{backupName});
} catch (ObjectDoesNotExist odne) {
LOG.warn(String.format("Backup '%s' does not exist. Ignoring...", backupName));
}
}
@Override
public void restoreHostBackup(LoadBalancerEndpointConfiguration config, String backupName) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
serviceStubs.getSystemBackupsBinding().restoreBackup(backupName);
}
@Override
public void setSubnetMappings(LoadBalancerEndpointConfiguration config, Hostssubnet hostssubnet) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String[] hosts = new String[]{hostssubnet.getHostsubnets().get(0).getName()};
TrafficIPGroupsSubnetMappingPerHost[] oldMap = serviceStubs.getTrafficIpGroupBinding().getSubnetMappings(hosts);
Hostssubnet oldHostssubnet = adapter2domainSubnetMapping(oldMap);
List<Hostssubnet> mergeMaps = new ArrayList<Hostssubnet>();
mergeMaps.add(hostssubnet);
mergeMaps.add(oldHostssubnet);
Hostssubnet newHostssubnet = domainUnionSubnetMapping(mergeMaps);
TrafficIPGroupsSubnetMappingPerHost[] zeusMap = domain2adaptorSubnetMapping(newHostssubnet);
serviceStubs.getTrafficIpGroupBinding().setSubnetMappings(zeusMap);
}
@Override
public void deleteSubnetMappings(LoadBalancerEndpointConfiguration config, Hostssubnet hostssubnet) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String[] hosts = new String[]{hostssubnet.getHostsubnets().get(0).getName()};
TrafficIPGroupsSubnetMappingPerHost[] oldMap = serviceStubs.getTrafficIpGroupBinding().getSubnetMappings(hosts);
Hostssubnet oldSubnet = adapter2domainSubnetMapping(oldMap);
Hostssubnet newSubnet = domainSubnetMappingRemove(oldSubnet, hostssubnet);
TrafficIPGroupsSubnetMappingPerHost[] newMap = domain2adaptorSubnetMapping(newSubnet);
serviceStubs.getTrafficIpGroupBinding().setSubnetMappings(newMap); // Sinze zues delete clobbers all mappings
// Use this bizare cherry pick method instead.
}
@Override
public Hostssubnet getSubnetMappings(LoadBalancerEndpointConfiguration config, String host) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String[] hosts = new String[]{host};
TrafficIPGroupsSubnetMappingPerHost[] zeusMap = serviceStubs.getTrafficIpGroupBinding().getSubnetMappings(hosts);
return adapter2domainSubnetMapping(zeusMap);
}
@Override
public List<String> getStatsSystemLoadBalancerNames(LoadBalancerEndpointConfiguration config) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
List<String> loadBalancerNames = new ArrayList<String>();
loadBalancerNames.addAll(Arrays.asList(serviceStubs.getSystemStatsBinding().getVirtualservers()));
return loadBalancerNames;
}
@Override
public Map<String, Integer> getLoadBalancerCurrentConnections(LoadBalancerEndpointConfiguration config, List<String> names)
throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Map<String, Integer> currentConnectionMap = new HashMap<String, Integer>();
int[] currentConnections = serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(names.toArray(new String[names.size()]));
for (int i = 0; i < names.size(); i++) {
currentConnectionMap.put(names.get(i), currentConnections[i]);
}
return currentConnectionMap;
}
@Override
public Integer getLoadBalancerCurrentConnections(LoadBalancerEndpointConfiguration config, Integer accountId, Integer loadBalancerId, boolean isSsl) throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = isSsl ? ZxtmNameBuilder.genSslVSName(loadBalancerId, accountId) : ZxtmNameBuilder.genVSName(loadBalancerId, accountId);
String virtualServerNames[] = {virtualServerName};
int[] ccsArray = serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(virtualServerNames);
return ccsArray[0];
}
@Override
public int getTotalCurrentConnectionsForHost(LoadBalancerEndpointConfiguration config) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
return serviceStubs.getSystemStatsBinding().getTotalCurrentConn();
}
@Override
public Stats getLoadBalancerStats(LoadBalancerEndpointConfiguration config, LoadBalancer loadBalancer) throws RemoteException, InsufficientRequestException {
List<ZxtmServiceStubs> allStubs = new ArrayList<ZxtmServiceStubs>();
for (URI endpoint : config.getSoapStatsEndpoints()) {
try {
allStubs.add(getStatsStubs(endpoint.toURL(), config));
} catch (MalformedURLException e) {
LOG.error(String.format("Creating stats bindings for endpoint %s failed.", endpoint), e);
}
}
// ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Stats stats = new Stats();
String virtualServerName;
if (loadBalancer.isSecureOnly() && loadBalancer.isHttpsRedirect() != null && loadBalancer.isHttpsRedirect()) {
virtualServerName = ZxtmNameBuilder.genRedirectVSName(loadBalancer);
} else {
virtualServerName = ZxtmNameBuilder.genVSName(loadBalancer);
}
final String sslVirtualServerName = ZxtmNameBuilder.genSslVSName(loadBalancer);
int[] connectionTimedOut = new int[1];
int[] connectionError = new int[1];
int[] connectionFailure = new int[1];
int[] dataTimedOut = new int[1];
int[] keepaliveTimedOut = new int[1];
int[] maxConnections = new int[]{0};
int[] currentConnections = new int[1];
int[] connectionTimedOutSsl = new int[1];
int[] connectionErrorSsl = new int[1];
int[] connectionFailureSsl = new int[1];
int[] dataTimedOutSsl = new int[1];
int[] keepaliveTimedOutSsl = new int[1];
int[] maxConnectionsSsl = new int[1];
int[] currentConnectionsSsl = new int[1];
if (!loadBalancer.isSecureOnly() && (loadBalancer.isHttpsRedirect() == null || !loadBalancer.isHttpsRedirect())) {
for (ZxtmServiceStubs serviceStubs : allStubs) {
connectionTimedOut[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectTimedOut(new String[]{virtualServerName})[0];
connectionError[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectionErrors(new String[]{virtualServerName})[0];
connectionFailure[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectionFailures(new String[]{virtualServerName})[0];
dataTimedOut[0] += serviceStubs.getSystemStatsBinding().getVirtualserverDataTimedOut(new String[]{virtualServerName})[0];
keepaliveTimedOut[0] += serviceStubs.getSystemStatsBinding().getVirtualserverKeepaliveTimedOut(new String[]{virtualServerName})[0];
currentConnections[0] += serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(new String[]{virtualServerName})[0];
int max = serviceStubs.getSystemStatsBinding().getVirtualserverMaxConn(new String[]{virtualServerName})[0];
if (max > maxConnections[0]) {
maxConnections[0] = max;
}
}
stats.setConnectTimeOut(connectionTimedOut);
stats.setConnectError(connectionError);
stats.setConnectFailure(connectionFailure);
stats.setDataTimedOut(dataTimedOut);
stats.setKeepAliveTimedOut(keepaliveTimedOut);
stats.setMaxConn(maxConnections);
stats.setCurrentConn(currentConnections);
} else {
stats.setConnectTimeOut(new int[]{0});
stats.setConnectError(new int[]{0});
stats.setConnectFailure(new int[]{0});
stats.setDataTimedOut(new int[]{0});
stats.setKeepAliveTimedOut(new int[]{0});
stats.setMaxConn(new int[]{0});
stats.setCurrentConn(new int[]{0});
}
if (loadBalancer.isUsingSsl()) {
for (ZxtmServiceStubs serviceStubs : allStubs) {
connectionTimedOutSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectTimedOut(new String[]{sslVirtualServerName})[0];
connectionErrorSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectionErrors(new String[]{sslVirtualServerName})[0];
connectionFailureSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverConnectionFailures(new String[]{sslVirtualServerName})[0];
dataTimedOutSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverDataTimedOut(new String[]{sslVirtualServerName})[0];
keepaliveTimedOutSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverKeepaliveTimedOut(new String[]{sslVirtualServerName})[0];
currentConnectionsSsl[0] += serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(new String[]{sslVirtualServerName})[0];
int maxSsl = serviceStubs.getSystemStatsBinding().getVirtualserverMaxConn(new String[]{sslVirtualServerName})[0];
if (maxSsl > maxConnectionsSsl[0]) {
maxConnectionsSsl[0] = maxSsl;
}
// stats.setConnectTimeOut(serviceStubs.getSystemStatsBinding().getVirtualserverConnectTimedOut(new String[]{virtualServerName}));
// stats.setConnectError(serviceStubs.getSystemStatsBinding().getVirtualserverConnectionErrors(new String[]{virtualServerName}));
// stats.setConnectFailure(serviceStubs.getSystemStatsBinding().getVirtualserverConnectionFailures(new String[]{virtualServerName}));
// stats.setDataTimedOut(serviceStubs.getSystemStatsBinding().getVirtualserverDataTimedOut(new String[]{virtualServerName}));
// stats.setKeepAliveTimedOut(serviceStubs.getSystemStatsBinding().getVirtualserverKeepaliveTimedOut(new String[]{virtualServerName}));
// stats.setMaxConn(serviceStubs.getSystemStatsBinding().getVirtualserverMaxConn(new String[]{virtualServerName}));
// stats.setCurrentConn(serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(new String[]{virtualServerName}));
// stats.setConnectTimeOutSsl(serviceStubs.getSystemStatsBinding().getVirtualserverConnectTimedOut(new String[]{sslVirtualServerName}));
// stats.setConnectErrorSsl(serviceStubs.getSystemStatsBinding().getVirtualserverConnectionErrors(new String[]{sslVirtualServerName}));
// stats.setConnectFailureSsl(serviceStubs.getSystemStatsBinding().getVirtualserverConnectionFailures(new String[]{sslVirtualServerName}));
// stats.setDataTimedOutSsl(serviceStubs.getSystemStatsBinding().getVirtualserverDataTimedOut(new String[]{sslVirtualServerName}));
// stats.setKeepAliveTimedOutSsl(serviceStubs.getSystemStatsBinding().getVirtualserverKeepaliveTimedOut(new String[]{sslVirtualServerName}));
// stats.setMaxConnSsl(serviceStubs.getSystemStatsBinding().getVirtualserverMaxConn(new String[]{sslVirtualServerName}));
// stats.setCurrentConnSsl(serviceStubs.getSystemStatsBinding().getVirtualserverCurrentConn(new String[]{sslVirtualServerName}));
}
stats.setConnectTimeOutSsl(connectionTimedOutSsl);
stats.setConnectErrorSsl(connectionErrorSsl);
stats.setConnectFailureSsl(connectionFailureSsl);
stats.setDataTimedOutSsl(dataTimedOutSsl);
stats.setKeepAliveTimedOutSsl(keepaliveTimedOutSsl);
stats.setMaxConnSsl(maxConnectionsSsl);
stats.setCurrentConnSsl(currentConnectionsSsl);
} else {
stats.setConnectTimeOutSsl(new int[]{0});
stats.setConnectErrorSsl(new int[]{0});
stats.setConnectFailureSsl(new int[]{0});
stats.setDataTimedOutSsl(new int[]{0});
stats.setKeepAliveTimedOutSsl(new int[]{0});
stats.setMaxConnSsl(new int[]{0});
stats.setCurrentConnSsl(new int[]{0});
}
return stats;
}
@Override
public Map<String, Long> getLoadBalancerBytesIn(LoadBalancerEndpointConfiguration config, List<String> names) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Map<String, Long> bytesInMap = new HashMap<String, Long>();
long[] bytesIn = serviceStubs.getSystemStatsBinding().getVirtualserverBytesIn(
names.toArray(new String[names.size()]));
for (int i = 0; i < names.size(); i++) {
bytesInMap.put(names.get(i), bytesIn[i]);
}
return bytesInMap;
}
@Override
public Long getLoadBalancerBytesIn(LoadBalancerEndpointConfiguration config, Integer accountId, Integer loadBalancerId, boolean isSsl) throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = isSsl ? ZxtmNameBuilder.genSslVSName(loadBalancerId, accountId) : ZxtmNameBuilder.genVSName(loadBalancerId, accountId);
String virtualServerNames[] = {virtualServerName};
long[] bytesInArray = serviceStubs.getSystemStatsBinding().getVirtualserverBytesIn(virtualServerNames);
return bytesInArray[0];
}
@Override
public Map<String, Long> getLoadBalancerBytesOut(LoadBalancerEndpointConfiguration config, List<String> names) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
Map<String, Long> bytesOutMap = new HashMap<String, Long>();
long[] bytesOut = serviceStubs.getSystemStatsBinding().getVirtualserverBytesOut(
names.toArray(new String[names.size()]));
for (int i = 0; i < names.size(); i++) {
bytesOutMap.put(names.get(i), bytesOut[i]);
}
return bytesOutMap;
}
@Override
public Long getLoadBalancerBytesOut(LoadBalancerEndpointConfiguration config, Integer accountId, Integer loadBalancerId, boolean isSsl) throws RemoteException, InsufficientRequestException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
String virtualServerName = isSsl ? ZxtmNameBuilder.genSslVSName(loadBalancerId, accountId) : ZxtmNameBuilder.genVSName(loadBalancerId, accountId);
String virtualServerNames[] = {virtualServerName};
long[] bytesOutArray = serviceStubs.getSystemStatsBinding().getVirtualserverBytesOut(virtualServerNames);
return bytesOutArray[0];
}
@Override
public Long getHostBytesIn(LoadBalancerEndpointConfiguration config) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
return serviceStubs.getSystemStatsBinding().getTotalBytesIn();
}
@Override
public Long getHostBytesOut(LoadBalancerEndpointConfiguration config) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
return serviceStubs.getSystemStatsBinding().getTotalBytesOut();
}
@Override
public boolean isEndPointWorking(LoadBalancerEndpointConfiguration config) throws RemoteException {
try {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
serviceStubs.getPoolBinding().getPoolNames();
return true;
} catch (AxisFault af) {
if (IpHelper.isNetworkConnectionException(af)) {
return false;
}
throw af;
}
}
private boolean[] generateBooleanArray(int size, boolean value) {
boolean[] array = new boolean[size];
for (boolean b : array) {
b = value;
}
return array;
}
private void createNodePool(LoadBalancerEndpointConfiguration config, Integer loadBalancerId, Integer accountId, Collection<Node> allNodes, LoadBalancerAlgorithm algorithm) throws RemoteException, InsufficientRequestException, ZxtmRollBackException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
final String poolName = ZxtmNameBuilder.genVSName(loadBalancerId, accountId);
LOG.debug(String.format("Creating pool '%s' and setting nodes...", poolName));
serviceStubs.getPoolBinding().addPool(new String[]{poolName}, NodeHelper.getIpAddressesFromNodes(allNodes));
setLoadBalancingAlgorithm(config, loadBalancerId, accountId, algorithm);
setDisabledNodes(config, poolName, getNodesWithCondition(allNodes, NodeCondition.DISABLED));
setDrainingNodes(config, poolName, getNodesWithCondition(allNodes, NodeCondition.DRAINING));
setNodeWeights(config, loadBalancerId, accountId, allNodes);
serviceStubs.getPoolBinding().setPassiveMonitoring(new String[]{poolName}, new boolean[]{false});
}
private List<Node> getNodesWithCondition(Collection<Node> nodes, NodeCondition nodeCondition) {
List<Node> nodesWithCondition = new ArrayList<Node>();
for (Node node : nodes) {
if (node.getCondition().equals(nodeCondition)) {
nodesWithCondition.add(node);
}
}
return nodesWithCondition;
}
/*
* Returns true is the protection class is brand new. Returns false if it already exists.
*/
private boolean addProtectionClass(LoadBalancerEndpointConfiguration config, String poolName) throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
boolean isNewProtectionClass = true;
try {
LOG.debug(String.format("Adding protection class '%s'...", poolName));
serviceStubs.getProtectionBinding().addProtection(new String[]{poolName});
LOG.info(String.format("Protection class '%s' successfully added.", poolName));
} catch (ObjectAlreadyExists oae) {
LOG.debug(String.format("Protection class '%s' already exists. Ignoring...", poolName));
isNewProtectionClass = false;
}
return isNewProtectionClass;
}
private void addMonitorClass(LoadBalancerEndpointConfiguration config, String monitorName)
throws RemoteException {
ZxtmServiceStubs serviceStubs = getServiceStubs(config);
try {
LOG.debug(String.format("Adding monitor class '%s'...", monitorName));
serviceStubs.getMonitorBinding().addMonitors(new String[]{monitorName});
LOG.info(String.format("Monitor class '%s' successfully added.", monitorName));
} catch (ObjectAlreadyExists oae) {
LOG.debug(String.format("Monitor class '%s' already exists. Ignoring...", monitorName));
}
}
// Translates from the transfer object "PersistenceMode" to an array of
// strings, which is used for Zeus.
private String[] getPersistenceMode(SessionPersistence mode) throws InsufficientRequestException {
if (mode == SessionPersistence.HTTP_COOKIE) {
return new String[]{HTTP_COOKIE};
} else if (mode == SessionPersistence.SOURCE_IP) {
return new String[]{SOURCE_IP};
} else if(mode == SessionPersistence.SSL_ID) {
return new String[]{SSL_ID};
} else {
throw new InsufficientRequestException("Unrecognized persistence mode.");
}
}
private PoolWeightingsDefinition[][] buildPoolWeightingsDefinition(Collection<Node> nodes) {
final PoolWeightingsDefinition[][] poolWeightings = new PoolWeightingsDefinition[1][nodes.size()];
final Integer DEFAULT_NODE_WEIGHT = 1;
int i = 0;
for (Node node : nodes) {
Integer nodeWeight = node.getWeight() == null ? DEFAULT_NODE_WEIGHT : node.getWeight();
poolWeightings[0][i] = new PoolWeightingsDefinition(IpHelper.createZeusIpString(node.getIpAddress(), node.getPort()), nodeWeight);
i++;
}
return poolWeightings;
}
private String[][] buildAccessListItems(Collection<AccessList> accessListItems, AccessListType type) throws InsufficientRequestException {
String[][] list;
if (type == AccessListType.ALLOW) {
List<AccessList> accessList = getFilteredList(accessListItems, AccessListType.ALLOW);
list = new String[1][accessList.size()];
for (int i = 0; i < accessList.size(); i++) {
list[0][i] = accessList.get(i).getIpAddress();
}
} else if (type == AccessListType.DENY) {
List<AccessList> accessList = getFilteredList(accessListItems, AccessListType.DENY);
list = new String[1][accessList.size()];
for (int i = 0; i < accessList.size(); i++) {
list[0][i] = accessList.get(i).getIpAddress();
}
} else {
throw new InsufficientRequestException(String.format("Unsupported rule type '%s' found when building item list", type));
}
return list;
}
private List<AccessList> getFilteredList(Collection<AccessList> accessListItems, AccessListType type) {
List<AccessList> filteredItems = new ArrayList<AccessList>();
for (AccessList item : accessListItems) {
if (item.getType() == type) {
filteredItems.add(item);
}
}
return filteredItems;
}
public static Hostssubnet domainSubnetMappingRemove(Hostssubnet oldNet, Hostssubnet removeItems) {
Hostssubnet out = new Hostssubnet();
int i;
Map<String, Map<String, Set<String>>> hmap = new HashMap<String, Map<String, Set<String>>>();
for (Hostsubnet hsubnet : oldNet.getHostsubnets()) {
String host = hsubnet.getName();
if (!hmap.containsKey(host)) {
hmap.put(host, new HashMap<String, Set<String>>());
}
for (NetInterface netInterface : hsubnet.getNetInterfaces()) {
String eth = netInterface.getName();
if (!hmap.get(host).containsKey(eth)) {
hmap.get(host).put(eth, new HashSet<String>());
}
for (Cidr cidr : netInterface.getCidrs()) {
String block = cidr.getBlock();
hmap.get(host).get(eth).add(cidr.getBlock());
}
}
}
// Trim oldNetHashMap
for (Hostsubnet hsubnet : removeItems.getHostsubnets()) {
String host = hsubnet.getName();
for (NetInterface netInterface : hsubnet.getNetInterfaces()) {
String eth = netInterface.getName();
for (Cidr cidr : netInterface.getCidrs()) {
String block = cidr.getBlock();
if (hmap.containsKey(host) && hmap.get(host).containsKey(eth)) {
hmap.get(host).get(eth).remove((String) block);
if (hmap.get(host).get(eth).isEmpty()) {
hmap.get(host).remove(eth);
}
if (hmap.get(host).isEmpty()) {
hmap.remove(host);
}
}
}
}
}
// copy surviving items
out = new Hostssubnet();
for (String host : hmap.keySet()) {
Hostsubnet hostsubnet = new Hostsubnet();
hostsubnet.setName(host);
for (String eth : hmap.get(host).keySet()) {
NetInterface netInterface = new NetInterface();
netInterface.setName(eth);
Object[] cidrObjs = hmap.get(host).get(eth).toArray();
for (i = 0; i < cidrObjs.length; i++) {
String cidrStr = (String) cidrObjs[i];
netInterface.getCidrs().add(new Cidr(cidrStr));
}
hostsubnet.getNetInterfaces().add(netInterface);
}
out.getHostsubnets().add(hostsubnet);
}
return out;
}
public static Hostssubnet domainUnionSubnetMapping(List<Hostssubnet> hostssubnets) {
int i;
Hostssubnet out = new Hostssubnet();
Map<String, Map<String, Set<String>>> hmap = new HashMap<String, Map<String, Set<String>>>();
for (Hostssubnet hostssubnet : hostssubnets) {
for (Hostsubnet hsubnet : hostssubnet.getHostsubnets()) {
String host = hsubnet.getName();
if (!hmap.containsKey(host)) {
hmap.put(host, new HashMap<String, Set<String>>());
}
for (NetInterface netInterface : hsubnet.getNetInterfaces()) {
String eth = netInterface.getName();
if (!hmap.get(host).containsKey(eth)) {
hmap.get(host).put(eth, new HashSet<String>());
}
for (Cidr cidr : netInterface.getCidrs()) {
String block = cidr.getBlock();
hmap.get(host).get(eth).add(cidr.getBlock());
}
}
}
}
out = new Hostssubnet();
for (String host : hmap.keySet()) {
Hostsubnet hostsubnet = new Hostsubnet();
hostsubnet.setName(host);
for (String eth : hmap.get(host).keySet()) {
NetInterface netInterface = new NetInterface();
netInterface.setName(eth);
Object[] cidrObjs = hmap.get(host).get(eth).toArray();
for (i = 0; i < cidrObjs.length; i++) {
String cidrStr = (String) cidrObjs[i];
netInterface.getCidrs().add(new Cidr(cidrStr));
}
hostsubnet.getNetInterfaces().add(netInterface);
}
out.getHostsubnets().add(hostsubnet);
}
return out;
}
private static Hostssubnet adapter2domainSubnetMapping(TrafficIPGroupsSubnetMappingPerHost[] zeusMap) {
int i;
int j;
int k;
Hostssubnet hostssubnet = new Hostssubnet();
for (i = 0; i < zeusMap.length; i++) {
Hostsubnet hostsubnet = new Hostsubnet();
String hostName = zeusMap[i].getHostname();
hostsubnet.setName(hostName);
TrafficIPGroupsSubnetMapping[] zsubnetMappings = zeusMap[i].getSubnetmappings();
for (j = 0; j < zsubnetMappings.length; j++) {
NetInterface iface = new NetInterface();
String interfaceName = zsubnetMappings[j].get_interface();
iface.setName(interfaceName);
String[] subNets = zsubnetMappings[j].getSubnets();
for (k = 0; k < subNets.length; k++) {
Cidr cidr = new Cidr();
cidr.setBlock(subNets[k]);
iface.getCidrs().add(cidr);
}
hostsubnet.getNetInterfaces().add(iface);
}
hostssubnet.getHostsubnets().add(hostsubnet);
}
return hostssubnet;
}
public static TrafficIPGroupsSubnetMappingPerHost[] domain2adaptorSubnetMapping(Hostssubnet hostssubnet) {
TrafficIPGroupsSubnetMappingPerHost[] zeusMap;
int i;
int j;
int k;
int smSize;
int cSize;
zeusMap = new TrafficIPGroupsSubnetMappingPerHost[hostssubnet.getHostsubnets().size()];
for (i = 0; i < hostssubnet.getHostsubnets().size(); i++) {
Hostsubnet hostsubnet = hostssubnet.getHostsubnets().get(i);
String hostName = hostsubnet.getName();
zeusMap[i] = new TrafficIPGroupsSubnetMappingPerHost();
zeusMap[i].setHostname(hostName);
smSize = hostsubnet.getNetInterfaces().size();
TrafficIPGroupsSubnetMapping[] zsubnetMappings;
zsubnetMappings = new TrafficIPGroupsSubnetMapping[smSize];
for (j = 0; j < hostsubnet.getNetInterfaces().size(); j++) {
NetInterface iface = hostsubnet.getNetInterfaces().get(j);
zsubnetMappings[j] = new TrafficIPGroupsSubnetMapping();
zsubnetMappings[j].set_interface(iface.getName());
cSize = iface.getCidrs().size();
String[] cidrs = new String[cSize];
for (k = 0; k < iface.getCidrs().size(); k++) {
cidrs[k] = iface.getCidrs().get(k).getBlock();
}
zsubnetMappings[j].setSubnets(cidrs);
}
zeusMap[i].setSubnetmappings(zsubnetMappings);
}
return zeusMap;
}
private String getErrorFileName(String vsName) {
String msg = String.format("%s_error.html", vsName);
return msg;
}
private boolean arrayElementSearch(String[] namesArray, String searchName) {
for (int n = 0; n < namesArray.length; n++) {
if (namesArray[n].equals(searchName)) {
return true;
}
}
return false;
}
}