int srcPort = loadBalancer.getSrcPort();
String lbProtocol = getNetScalerProtocol(loadBalancer);
String lbAlgorithm = loadBalancer.getAlgorithm();
String nsVirtualServerName = generateNSVirtualServerName(srcIp, srcPort);
String nsMonitorName = generateNSMonitorName(srcIp, srcPort);
LbSslCert sslCert = loadBalancer.getSslCert();
if (loadBalancer.isAutoScaleVmGroupTO()) {
applyAutoScaleConfig(loadBalancer);
// Continue to process all the rules.
continue;
}
boolean hasMonitor = false;
boolean deleteMonitor = false;
boolean destinationsToAdd = false;
boolean deleteCert = false;
for (DestinationTO destination : loadBalancer.getDestinations()) {
if (!destination.isRevoked()) {
destinationsToAdd = true;
break;
}
}
if (!loadBalancer.isRevoked() && destinationsToAdd) {
// create a load balancing virtual server
addLBVirtualServer(nsVirtualServerName, srcIp, srcPort, lbAlgorithm, lbProtocol, loadBalancer.getStickinessPolicies(), null);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Created load balancing virtual server " + nsVirtualServerName + " on the Netscaler device");
}
// create a new monitor
HealthCheckPolicyTO[] healthCheckPolicies = loadBalancer.getHealthCheckPolicies();
if ((healthCheckPolicies != null) && (healthCheckPolicies.length > 0) && (healthCheckPolicies[0] != null)) {
for (HealthCheckPolicyTO healthCheckPolicyTO : healthCheckPolicies) {
if (!healthCheckPolicyTO.isRevoked()) {
addLBMonitor(nsMonitorName, lbProtocol, healthCheckPolicyTO);
hasMonitor = true;
} else {
deleteMonitor = true;
hasMonitor = false;
}
}
}
for (DestinationTO destination : loadBalancer.getDestinations()) {
String nsServerName = generateNSServerName(destination.getDestIp());
String nsServiceName = generateNSServiceName(destination.getDestIp(), destination.getDestPort());
if (!destination.isRevoked()) {
// add a new destination to deployed load balancing rule
// add a new server
if (!nsServerExists(nsServerName)) {
com.citrix.netscaler.nitro.resource.config.basic.server nsServer = new com.citrix.netscaler.nitro.resource.config.basic.server();
nsServer.set_name(nsServerName);
nsServer.set_ipaddress(destination.getDestIp());
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.add(_netscalerService, nsServer);
if ((apiCallResult.errorcode != 0) && (apiCallResult.errorcode != NitroError.NS_RESOURCE_EXISTS)) {
throw new ExecutionException("Failed to add server " + destination.getDestIp() + " due to" + apiCallResult.message);
}
}
// create a new service using the server added
if (!nsServiceExists(nsServiceName)) {
com.citrix.netscaler.nitro.resource.config.basic.service newService = new com.citrix.netscaler.nitro.resource.config.basic.service();
newService.set_name(nsServiceName);
newService.set_port(destination.getDestPort());
newService.set_servername(nsServerName);
newService.set_state("ENABLED");
newService.set_servicetype(lbProtocol);
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.add(_netscalerService, newService);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to create service " + nsServiceName + " using server " + nsServerName + " due to" +
apiCallResult.message);
}
}
//bind service to load balancing virtual server
if (!nsServiceBindingExists(nsVirtualServerName, nsServiceName)) {
com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding svcBinding =
new com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding();
svcBinding.set_name(nsVirtualServerName);
svcBinding.set_servicename(nsServiceName);
apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.add(_netscalerService, svcBinding);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to bind service: " + nsServiceName + " to the lb virtual server: " + nsVirtualServerName +
" on Netscaler device");
}
}
// After binding the service to the LB Vserver
// successfully, bind the created monitor to the
// service.
if (hasMonitor) {
if (!isServiceBoundToMonitor(nsServiceName, nsMonitorName)) {
bindServiceToMonitor(nsServiceName, nsMonitorName);
}
} else {
// check if any monitor created by CS is already
// existing, if yes, unbind it from services and
// delete it.
if (nsMonitorExist(nsMonitorName)) {
// unbind the service from the monitor and
// delete the monitor
unBindServiceToMonitor(nsServiceName, nsMonitorName);
deleteMonitor = true;
}
}
if (sslCert != null && lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO)) {
if (sslCert.isRevoked()) {
deleteCert = true;
} else {
// If there is a chain, that should go first to the NS
String previousCertKeyName = null;
if (sslCert.getChain() != null) {
List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
// go from ROOT to intermediate CAs
for (Certificate intermediateCert : Lists.reverse(chainList)) {
String fingerPrint = CertificateHelper.generateFingerPrint(intermediateCert);
String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);
String intermediateCertFileName = intermediateCertKeyName + ".pem";
if (!SSL.isSslCertKeyPresent(_netscalerService, intermediateCertKeyName)) {
intermediateCert.getEncoded();
StringWriter textWriter = new StringWriter();
PEMWriter pemWriter = new PEMWriter(textWriter);
pemWriter.writeObject(intermediateCert);
pemWriter.flush();
SSL.uploadCert(_ip, _username, _password, intermediateCertFileName, textWriter.toString().getBytes());
SSL.createSslCertKey(_netscalerService, intermediateCertFileName, null, intermediateCertKeyName, null);
}
if (previousCertKeyName != null && !SSL.certLinkExists(_netscalerService, intermediateCertKeyName, previousCertKeyName)) {
SSL.linkCerts(_netscalerService, intermediateCertKeyName, previousCertKeyName);
}
previousCertKeyName = intermediateCertKeyName;
}
}
String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
ByteArrayOutputStream certDataStream = new ByteArrayOutputStream();
certDataStream.write(sslCert.getCert().getBytes());
if (!SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
SSL.uploadCert(_ip, _username, _password, certFilename, certDataStream.toByteArray());
SSL.uploadKey(_ip, _username, _password, keyFilename, sslCert.getKey().getBytes());
SSL.createSslCertKey(_netscalerService, certFilename, keyFilename, certKeyName, sslCert.getPassword());
}
if (previousCertKeyName != null && !SSL.certLinkExists(_netscalerService, certKeyName, previousCertKeyName)) {
SSL.linkCerts(_netscalerService, certKeyName, previousCertKeyName);
}
SSL.bindCertKeyToVserver(_netscalerService, certKeyName, nsVirtualServerName);
}
}
if (s_logger.isDebugEnabled()) {
s_logger.debug("Successfully added LB destination: " + destination.getDestIp() + ":" + destination.getDestPort() + " to load balancer " +
srcIp + ":" + srcPort);
}
} else {
// remove a destination from the deployed load balancing rule
com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings =
com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, nsVirtualServerName);
if (serviceBindings != null) {
for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) {
if (nsServiceName.equalsIgnoreCase(binding.get_servicename())) {
// delete the binding
apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(_netscalerService, binding);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to delete the binding between the virtual server: " + nsVirtualServerName +
" and service:" + nsServiceName + " due to" + apiCallResult.message);
}
// check if service is bound to any other virtual server
if (!isServiceBoundToVirtualServer(nsServiceName)) {
// no lb virtual servers are bound to this service so delete it
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, nsServiceName);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to delete service: " + nsServiceName + " due to " + apiCallResult.message);
}
}
// delete the server if there is no associated services
server_service_binding[] services = server_service_binding.get(_netscalerService, nsServerName);
if ((services == null) || (services.length == 0)) {
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to remove server:" + nsServerName + " due to " + apiCallResult.message);
}
}
}
}
}
}
}
} else {
// delete the implemented load balancing rule and its destinations
lbvserver lbserver = getVirtualServerIfExisits(nsVirtualServerName);
if (lbserver != null) {
//unbind the all services associated with this virtual server
com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding[] serviceBindings =
com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.get(_netscalerService, nsVirtualServerName);
if (serviceBindings != null) {
for (com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding binding : serviceBindings) {
String serviceName = binding.get_servicename();
apiCallResult = com.citrix.netscaler.nitro.resource.config.lb.lbvserver_service_binding.delete(_netscalerService, binding);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to unbind service from the lb virtual server: " + nsVirtualServerName + " due to " +
apiCallResult.message);
}
com.citrix.netscaler.nitro.resource.config.basic.service svc =
com.citrix.netscaler.nitro.resource.config.basic.service.get(_netscalerService, serviceName);
String nsServerName = svc.get_servername();
// check if service is bound to any other virtual server
if (!isServiceBoundToVirtualServer(serviceName)) {
// no lb virtual servers are bound to this service so delete it
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.service.delete(_netscalerService, serviceName);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to delete service: " + serviceName + " due to " + apiCallResult.message);
}
}
//delete the server if no more services attached
server_service_binding[] services = server_service_binding.get(_netscalerService, nsServerName);
if ((services == null) || (services.length == 0)) {
apiCallResult = com.citrix.netscaler.nitro.resource.config.basic.server.delete(_netscalerService, nsServerName);
if (apiCallResult.errorcode != 0) {
throw new ExecutionException("Failed to remove server:" + nsServerName + " due to " + apiCallResult.message);
}
}
}
}
removeLBVirtualServer(nsVirtualServerName);
deleteMonitor = true;
deleteCert = true;
}
}
if (deleteMonitor) {
removeLBMonitor(nsMonitorName);
}
if (sslCert != null && deleteCert) {
String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
// unbind before deleting
if (nsVirtualServerExists(nsVirtualServerName) &&
SSL.isSslCertKeyPresent(_netscalerService, certKeyName) &&
SSL.isBoundToVserver(_netscalerService, certKeyName, nsVirtualServerName)) {
SSL.unbindCertKeyFromVserver(_netscalerService, certKeyName, nsVirtualServerName);
}
if (SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
SSL.deleteSslCertKey(_netscalerService, certKeyName);
SSL.deleteCertFile(_ip, _username, _password, certFilename);
SSL.deleteKeyFile(_ip, _username, _password, keyFilename);
}
/*
* Check and delete intermediate certs:
* we can delete an intermediate cert if no other
* cert references it as the athority
*/
if (sslCert.getChain() != null) {
List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
//go from intermediate CAs to ROOT
for (Certificate intermediateCert : chainList) {
String fingerPrint = CertificateHelper.generateFingerPrint(intermediateCert);
String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);