package org.openstack.atlas.api.mgmt.async; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openstack.atlas.api.helpers.NodesHelper; import org.openstack.atlas.docs.loadbalancers.api.v1.SslTermination; import org.openstack.atlas.service.domain.entities.LoadBalancer; import org.openstack.atlas.service.domain.entities.LoadBalancerStatus; import org.openstack.atlas.service.domain.entities.UserPages; import org.openstack.atlas.service.domain.events.UsageEvent; import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException; import org.openstack.atlas.service.domain.exceptions.UsageEventCollectionException; import org.openstack.atlas.service.domain.pojos.MessageDataContainer; import org.openstack.atlas.service.domain.pojos.ZeusSslTermination; import org.openstack.atlas.service.domain.services.helpers.AlertType; import org.openstack.atlas.usagerefactor.SnmpUsage; import org.openstack.atlas.util.debug.Debug; import javax.jms.Message; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import static org.openstack.atlas.service.domain.entities.LoadBalancerStatus.*; import static org.openstack.atlas.service.domain.entities.NodeStatus.ONLINE; import static org.openstack.atlas.service.domain.events.entities.CategoryType.CREATE; import static org.openstack.atlas.service.domain.events.entities.CategoryType.DELETE; import static org.openstack.atlas.service.domain.events.entities.EventSeverity.INFO; import static org.openstack.atlas.service.domain.events.entities.EventType.CREATE_LOADBALANCER; import static org.openstack.atlas.service.domain.events.entities.EventType.DELETE_LOADBALANCER; import static org.openstack.atlas.service.domain.services.helpers.AlertType.USAGE_FAILURE; public class SyncListener extends BaseListener { final Log LOG = LogFactory.getLog(SyncListener.class); @Override public void doOnMessage(Message message) throws Exception { LOG.debug("Entering " + getClass()); LOG.debug(message); LoadBalancer dbLoadBalancer; MessageDataContainer mdc = getDataContainerFromMessage(message); LoadBalancerStatus finalStatus = ACTIVE; try { dbLoadBalancer = loadBalancerService.getWithUserPages(mdc.getLoadBalancerId(), mdc.getAccountId()); } catch (EntityNotFoundException enfe) { LOG.error(String.format("EntityNotFoundException thrown while attempting to sync Loadbalancer #%d: ", mdc.getLoadBalancerId())); return; } LOG.debug(String.format("Synchronizing load balancer #%d with database configuration", mdc.getLoadBalancerId())); final LoadBalancerStatus loadBalancerStatus = mdc.getStatus(); List<SnmpUsage> usages = new ArrayList<SnmpUsage>(); try { LOG.info(String.format("Collecting DELETE_LOADBALANCER usage for load balancer %s...", dbLoadBalancer.getId())); usages = usageEventCollection.getUsage(dbLoadBalancer); LOG.info(String.format("Successfully collected DELETE_LOADBALANCER usage for load balancer %s", dbLoadBalancer.getId())); } catch (UsageEventCollectionException e) { LOG.error(String.format("Collection of the DELETE_LOADBALANCER usage event failed for " + "load balancer: %s :: Exception: %s", dbLoadBalancer.getId(), e)); } if (loadBalancerStatus.equals(PENDING_DELETE) || loadBalancerStatus.equals(DELETED)) { finalStatus = DELETED; try { if (!isRestAdapter()) { LOG.debug(String.format("Removing loadbalancer for sync in ZXTM for LB: %s", dbLoadBalancer.getId())); reverseProxyLoadBalancerService.deleteLoadBalancer(dbLoadBalancer); LOG.debug(String.format("Successfully removed loadbalancer for sync in ZXTM for LB: %s", dbLoadBalancer.getId())); } } catch (Exception e) { String msg = String.format("Error deleting loadbalancer #%d in SyncListener(): ", mdc.getLoadBalancerId()); loadBalancerService.setStatus(dbLoadBalancer, ERROR); notificationService.saveAlert(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), e, AlertType.ZEUS_FAILURE.name(), msg); LOG.error(msg, e); } loadBalancerService.pseudoDelete(dbLoadBalancer); if (loadBalancerStatus.equals(PENDING_DELETE)) { // Add atom entry String atomTitle = "Load Balancer Successfully Deleted"; String atomSummary = "Load balancer successfully deleted"; notificationService.saveLoadBalancerEvent(dbLoadBalancer.getUserName(), dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), atomTitle, atomSummary, DELETE_LOADBALANCER, DELETE, INFO); // Notify usage processor Calendar eventTime = Calendar.getInstance(); LOG.info(String.format("Processing DELETE_LOADBALANCER usage for load balancer %s...", dbLoadBalancer.getId())); try { usageEventCollection.processUsageEvent(usages, dbLoadBalancer, UsageEvent.DELETE_LOADBALANCER, eventTime); LOG.info(String.format("Completed processing DELETE_LOADBALANCER usage for load balancer %s", dbLoadBalancer.getId())); } catch (Exception exc) { String exceptionStackTrace = Debug.getExtendedStackTrace(exc); String usageAlertDescription = String.format("An error occurred while processing the usage for an event on loadbalancer %d: \n%s\n\n%s", dbLoadBalancer.getId(), exc.getMessage(), exceptionStackTrace); LOG.error(usageAlertDescription); notificationService.saveAlert(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), exc, USAGE_FAILURE.name(), usageAlertDescription); } //Set status record loadBalancerStatusHistoryService.save(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), LoadBalancerStatus.PENDING_DELETE); } } else { try { LOG.debug(String.format("Syncing load balancer %s setting status to PENDING_UPDATE", dbLoadBalancer.getId())); if (isRestAdapter()) { LOG.debug(String.format("Updating loadbalancer: %s in STM...", dbLoadBalancer.getId())); reverseProxyLoadBalancerStmService.updateLoadBalancer(dbLoadBalancer, dbLoadBalancer, loadBalancerService.getUserPages(dbLoadBalancer.getId(), dbLoadBalancer.getAccountId())); LOG.debug(String.format("Successfully Updated loadbalancer: %s in STM...", dbLoadBalancer.getId())); } else { LOG.debug(String.format("Syncing loadbalancer: %s in ZXTM...", dbLoadBalancer.getId())); reverseProxyLoadBalancerService.syncLoadBalancer(dbLoadBalancer); LOG.debug(String.format("Successfully synced loadbalancer: %s in ZXTM...", dbLoadBalancer.getId())); } LOG.debug(String.format("Sync of load balancer %s complete, updating status and saving events and usage...", dbLoadBalancer.getId())); if (loadBalancerStatus.equals(BUILD)) { NodesHelper.setNodesToStatus(dbLoadBalancer, ONLINE); dbLoadBalancer = loadBalancerService.update(dbLoadBalancer); //not sure if this is still needed // Add atom entry String atomTitle = "Load Balancer Successfully Created"; String atomSummary = createAtomSummary(dbLoadBalancer).toString(); notificationService.saveLoadBalancerEvent(dbLoadBalancer.getUserName(), dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), atomTitle, atomSummary, CREATE_LOADBALANCER, CREATE, INFO); // Notify old usage processor Calendar eventTime = Calendar.getInstance(); try { usageEventCollection.processZeroUsageEvent(dbLoadBalancer, UsageEvent.CREATE_LOADBALANCER, eventTime); } catch (UsageEventCollectionException uex) { LOG.error(String.format("Collection and processing of the usage event failed for load balancer: %s " + ":: Exception: %s", dbLoadBalancer.getId(), uex)); } catch (Exception exc) { String exceptionStackTrace = Debug.getExtendedStackTrace(exc); String usageAlertDescription = String.format("An error occurred while processing the usage for an event on loadbalancer %d: \n%s\n\n%s", dbLoadBalancer.getId(), exc.getMessage(), exceptionStackTrace); LOG.error(usageAlertDescription); notificationService.saveAlert(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), exc, USAGE_FAILURE.name(), usageAlertDescription); } } } catch (Exception e) { String msg = String.format("Error re-creating loadbalancer #%d in SyncListener(), " + "setting status to ERROR, original status: %s:", mdc.getLoadBalancerId(), loadBalancerStatus); finalStatus = ERROR; notificationService.saveAlert(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), e, AlertType.ZEUS_FAILURE.name(), msg); LOG.error(msg, e); } try { //Now create the secure VS if ssl termination was already on the loadbalancer... if (dbLoadBalancer.hasSsl() && (loadBalancerStatus.equals(PENDING_UPDATE) || loadBalancerStatus.equals(ERROR))) { Calendar eventTime = Calendar.getInstance(); try { if (dbLoadBalancer.isUsingSsl()) { if (dbLoadBalancer.getSslTermination().isSecureTrafficOnly()) { usageEventCollection.collectUsageAndProcessUsageRecords(dbLoadBalancer, UsageEvent.SSL_ONLY_ON, eventTime); } else { usageEventCollection.collectUsageAndProcessUsageRecords(dbLoadBalancer, UsageEvent.SSL_MIXED_ON, eventTime); } } else { usageEventCollection.collectUsageAndProcessUsageRecords(dbLoadBalancer, UsageEvent.SSL_OFF, eventTime); } } catch (Exception exc) { String exceptionStackTrace = Debug.getExtendedStackTrace(exc); String usageAlertDescription = String.format("An error occurred while processing the usage for an event on loadbalancer %d: \n%s\n\n%s", dbLoadBalancer.getId(), exc.getMessage(), exceptionStackTrace); LOG.error(usageAlertDescription); notificationService.saveAlert(dbLoadBalancer.getAccountId(), dbLoadBalancer.getId(), exc, USAGE_FAILURE.name(), usageAlertDescription); } } } catch (Exception e) { String msg = String.format("Error re-creating ssl terminated loadbalancer #%d in SyncListener(), " + "setting status to ERROR, original status: :", mdc.getLoadBalancerId(), loadBalancerStatus); finalStatus = ERROR; LOG.error(msg, e); } } loadBalancerService.setStatus(dbLoadBalancer, finalStatus); LOG.info(String.format("Sync operation complete for loadbalancer #%d ", mdc.getLoadBalancerId())); } private StringBuilder createAtomSummary(LoadBalancer lb) { StringBuilder atomSummary = new StringBuilder(); atomSummary.append("Load balancer successfully created with "); atomSummary.append("name: '").append(lb.getName()).append("', "); atomSummary.append("algorithm: '").append(lb.getAlgorithm()).append("', "); atomSummary.append("protocol: '").append(lb.getProtocol()).append("', "); atomSummary.append("port: '").append(lb.getPort()).append("'"); return atomSummary; } }