package org.openstack.atlas.service.domain.services.impl; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openstack.atlas.service.domain.entities.Node; import org.openstack.atlas.service.domain.entities.NodeStatus; import org.openstack.atlas.service.domain.exceptions.BadRequestException; import org.openstack.atlas.service.domain.exceptions.EntityNotFoundException; import org.openstack.atlas.service.domain.pojos.ZeusEvent; import org.openstack.atlas.service.domain.services.CallbackService; import org.openstack.atlas.service.domain.services.NodeService; import org.openstack.atlas.service.domain.services.NotificationService; import org.openstack.atlas.service.domain.services.helpers.CallbackHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import static org.openstack.atlas.service.domain.events.entities.CategoryType.UPDATE; import static org.openstack.atlas.service.domain.events.entities.EventSeverity.INFO; import static org.openstack.atlas.service.domain.events.entities.EventType.UPDATE_NODE; import static org.openstack.atlas.service.domain.services.helpers.CallbackHelper.*; @Service public class CallbackServiceImpl extends BaseService implements CallbackService { private final Log LOG = LogFactory.getLog(CallbackServiceImpl.class); @Autowired private NodeService nodeService; @Autowired private NotificationService notificationService; public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setNotificationService(NotificationService notificationService) { this.notificationService = notificationService; } //V1-B-34716 @Override @Transactional public void handleZeusEvent(ZeusEvent zeusEvent) throws BadRequestException { //Example paramLines:: //WARN monitors/571432_62203 monitorfail Monitor has detected a failure in node '10.178.224.134:443': Invalid HTTP response received; premature end of headers //INFO monitors/571432_62203 monitorok Monitor is working for node '10.178.224.134:443'. if (zeusEvent.getParamLine().contains(MONITOR_FAIL_TAG) || zeusEvent.getParamLine().contains(MONITOR_WORKING_TAG)) { LOG.debug("Node status changed."); } else { LOG.warn("Unsupported callback event triggered. Dropping request..."); throw new BadRequestException("We currently do not support this callback request."); } try { CallbackHelper callbackHelper = new CallbackHelper(zeusEvent.getParamLine()); Integer loadBalancerId = callbackHelper.loadBalancerId; String ipAddress = callbackHelper.ipAddress; Integer ipPort = callbackHelper.port; Node dbNode = nodeService.getNodeByLoadBalancerIdIpAddressAndPort(loadBalancerId, ipAddress, ipPort); String status; if (zeusEvent.getParamLine().contains(MONITOR_FAIL_TAG)) { dbNode.setStatus(NodeStatus.OFFLINE); status = NodeStatus.OFFLINE.name(); } else if (zeusEvent.getParamLine().contains(MONITOR_WORKING_TAG)) { dbNode.setStatus(NodeStatus.ONLINE); status = NodeStatus.ONLINE.name(); } else { throw new BadRequestException("We currently do not support this callback request."); } nodeService.updateNodeStatus(dbNode); // Add atom entry String atomTitle = "Node Status Updated"; String atomSummary = String.format("Node '%d' status changed to '%s' for load balancer '%d'", dbNode.getId(), status, loadBalancerId); String detailedMessage = ""; String callbackHost = zeusEvent.getCallbackHost(); detailedMessage = (callbackHelper.detailedMessage.equals("")) ? "Node is working" : callbackHelper.detailedMessage; notificationService.saveNodeServiceEvent("Rackspace Cloud", dbNode.getLoadbalancer().getAccountId(), loadBalancerId, dbNode.getId(), atomTitle, atomSummary, UPDATE_NODE, UPDATE, INFO, detailedMessage, callbackHost); LOG.info(String.format("Node '%d' status changed to '%s' for load balancer '%d'", dbNode.getId(), status, loadBalancerId)); } catch (Exception e) { String message; if (e instanceof EntityNotFoundException) { message = String.format("Could not process Zeus event as node could not be found: '%s'", zeusEvent.getParamLine()); } else { message = String.format("Could not process Zeus event: '%s'", zeusEvent.getParamLine()); } LOG.warn(message); throw new BadRequestException(message, e); } } // @Override // @Transactional // public void handleZeusEvent(ZeusEvent zeusEvent) throws BadRequestException { // // Example ipv4 paramLine: "INFO pools/501148_11066 nodes/10.179.78.70:80 nodeworking Node 10.179.78.70 is working again" // // Example ipv6 paramLine: "INFO pools/501148_11066 nodes/[fe80::4240:adff:fe5c:c9ee]:80 nodeworking Node fe80::4240:adff:fe5c:c9ee is working again" // // if (zeusEvent.getParamLine().contains(NODE_FAIL_TAG) || zeusEvent.getParamLine().contains(NODE_WORKING_TAG)) { // LOG.debug("Node status changed."); // } else { // LOG.warn("Unsupported callback event triggered. Dropping request..."); // throw new BadRequestException("We currently do not support this callback request."); // } // // try { // Integer loadBalancerId = getLoadbalancerId(zeusEvent.getParamLine()); // String ipAddress = getIpAddress(zeusEvent.getParamLine()); // Integer ipPort = getIpPort(zeusEvent.getParamLine()); // Node dbNode = nodeService.getNodeByLoadBalancerIdIpAddressAndPort(loadBalancerId, ipAddress, ipPort); // String status; // // if (zeusEvent.getParamLine().contains(NODE_FAIL_TAG)) { // dbNode.setStatus(NodeStatus.OFFLINE); // status = NodeStatus.OFFLINE.name(); // } else if (zeusEvent.getParamLine().contains(NODE_WORKING_TAG)) { // dbNode.setStatus(NodeStatus.ONLINE); // status = NodeStatus.ONLINE.name(); // } else { // throw new BadRequestException("We currently do not support this callback request."); // } // // nodeService.updateNodeStatus(dbNode); // // // Add atom entry // String atomTitle = "Node Status Updated"; // String atomSummary = String.format("Node '%d' status changed to '%s' for load balancer '%d'", dbNode.getId(), status, loadBalancerId); // notificationService.saveNodeServiceEvent("Rackspace Cloud", dbNode.getLoadbalancer().getAccountId(), loadBalancerId, dbNode.getId(), atomTitle, atomSummary, UPDATE_NODE, UPDATE, INFO, zeusEvent.getParamLine()); // // LOG.info(String.format("Node '%d' status changed to '%s' for load balancer '%d'", dbNode.getId(), status, loadBalancerId)); // } catch (Exception e) { // String message; // if (e instanceof EntityNotFoundException) { // message = String.format("Could not process Zeus event as node could not be found: '%s'", zeusEvent.getParamLine()); // } else { // message = String.format("Could not process Zeus event: '%s'", zeusEvent.getParamLine()); // } // LOG.warn(message); // throw new BadRequestException(message, e); // } // } // public Integer getLoadbalancerId(String paramLine) throws Exception { // String poolsObject = paramLine.split(" ")[1]; // String poolName = poolsObject.split("/")[1]; // String loadbalancerId = poolName.split("_")[1]; // // try { // return Integer.parseInt(loadbalancerId); // } catch (NumberFormatException e) { // LOG.warn(String.format("Error converting string to integer for load balancer id: '%s'", loadbalancerId)); // throw new Exception(e); // } // } // // public String getIpAddress(String paramLine) { //// String nodesObject = paramLine.split(" ")[2]; //// String ipAddressWithPort = nodesObject.split("/")[1]; //// return ipAddressWithPort.split(":")[0].replace("[", ""); // String nodeLine = paramLine.split("Node ")[1]; // return nodeLine.split(" ")[0]; // } // // public Integer getIpPort(String paramLine) throws Exception { // String nodesObject = paramLine.split(" ")[2]; // String ipAddressWithPort = nodesObject.split("/")[1]; // String port = ipAddressWithPort.split(":")[1]; // // try { // return Integer.parseInt(port); // } catch (NumberFormatException e) { // LOG.info("Error parsing paramline for ipv4, trying for ipv6"); // } // return getIpPortForIpv6(paramLine); // } // // public Integer getIpPortForIpv6(String paramLine) throws Exception { // String nodesObject = paramLine.split(" ")[2]; // String ipAddressWithPort = nodesObject.split("/")[1]; // String port = ipAddressWithPort.split("]:")[1]; // // try { // return Integer.parseInt(port); // } catch (NumberFormatException e) { // LOG.warn(String.format("Error converting string to integer for port: '%s'", port)); // throw new Exception(e); // } // } }