Updated Branches: refs/heads/master 1dba19acc -> 5d8ab42f9
Implemented haproxy statistics reporting feature Project: http://git-wip-us.apache.org/repos/asf/incubator-stratos/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-stratos/commit/5d8ab42f Tree: http://git-wip-us.apache.org/repos/asf/incubator-stratos/tree/5d8ab42f Diff: http://git-wip-us.apache.org/repos/asf/incubator-stratos/diff/5d8ab42f Branch: refs/heads/master Commit: 5d8ab42f9034d69421a552510b4b730cd3f28972 Parents: 1dba19a Author: Imesh Gunaratne <[email protected]> Authored: Sun Nov 17 10:37:41 2013 +0530 Committer: Imesh Gunaratne <[email protected]> Committed: Sun Nov 17 10:37:41 2013 +0530 ---------------------------------------------------------------------- .../load-balancer/haproxy-extension/INSTALL.txt | 23 ++++ .../load-balancer/haproxy-extension/README.txt | 26 +++++ .../haproxy-extension/src/main/assembly/bin.xml | 10 +- .../src/main/bin/haproxy-extension.sh | 21 ++-- .../stratos/haproxy/extension/CommandUtil.java | 66 ++++++++++++ .../stratos/haproxy/extension/HAProxy.java | 62 ++++------- .../haproxy/extension/HAProxyConfigWriter.java | 55 +++++----- .../haproxy/extension/HAProxyContext.java | 104 +++++++++++++++++++ .../haproxy/extension/HAProxyStatsReader.java | 63 +++++++++++ .../apache/stratos/haproxy/extension/Main.java | 35 ++----- .../src/main/resources/log4j.properties | 37 ------- .../src/main/scripts/get-weight.sh | 23 ++++ .../src/main/templates/haproxy.cfg.template | 2 +- 13 files changed, 380 insertions(+), 147 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/INSTALL.txt ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/INSTALL.txt b/extensions/load-balancer/haproxy-extension/INSTALL.txt new file mode 100644 index 0000000..ef9e3dc --- /dev/null +++ b/extensions/load-balancer/haproxy-extension/INSTALL.txt @@ -0,0 +1,23 @@ +================================================================================ + Installing Apache Stratos HAProxy Extension 4.0.0-SNAPSHOT +================================================================================ + + +Apache Stratos HAProxy Extension could be run in an unix environment. Please follow the +below steps to proceed with the installation: + +1. Download and extract HAProxy binary distribution to a desired location: <HAPROXY-HOME>. + +2. Extract apache-stratos-haproxy-extension-4.0.0-SNAPSHOT-bin.zip to a desired location: <HAPROXY-EXTENSION-HOME>. + +3. Open <HAPROXY-EXTENSION-HOME>/bin/haproxy-extension.sh in a text editor and update following system properties: + + -Dexecutable.file.path=<HAPROXY-HOME>/haproxy # HAProxy executable file path + -Dconf.file.path=/tmp/haproxy.cfg # HAProxy configuration file path + -Dstats.socket.file.path=/tmp/haproxy-stats.socket # HAProxy statistics socket file path + -Dthrift.receiver.ip=localhost # CEP IP Address + -Dthrift.receiver.port=7615 # CEP Port + + +Thank you for using Apache Stratos! +Apache Stratos Team http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/README.txt ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/README.txt b/extensions/load-balancer/haproxy-extension/README.txt new file mode 100644 index 0000000..6131bff --- /dev/null +++ b/extensions/load-balancer/haproxy-extension/README.txt @@ -0,0 +1,26 @@ +================================================================================ + Apache Stratos HAProxy Extension 4.0.0-SNAPSHOT +================================================================================ + + +Apache Stratos (incubating) HAProxy extension is a load balancer extension for HAProxy. +It is an executable program which could manage the life-cycle of a HAProxy instance +according to topology updates received from Stratos Cloud Controller via the message broker. + +Work Flow: +1. Wait for the complete topology event message to initialize the topology. +2. Configure and start an instance of HAProxy. +3. Listen to topology update messages. +4. Reload HAProxy instance with the new topology configuration. +5. Periodically publish statistics to Complex Event Processor (CEP). + +Please refer INSTALL.txt for information on the installation process. + + +Thanks to Vaadin for HAProxyController implementation: +https://vaadin.com/license +http://dev.vaadin.com/browser/svn/incubator/Arvue/ArvueMaster/src/org/vaadin/arvue/arvuemaster/HAProxyController.java + + +Thank you for using Apache Stratos! +Apache Stratos Team http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/assembly/bin.xml ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/assembly/bin.xml b/extensions/load-balancer/haproxy-extension/src/main/assembly/bin.xml index c21b4b0..34c1db8 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/assembly/bin.xml +++ b/extensions/load-balancer/haproxy-extension/src/main/assembly/bin.xml @@ -59,13 +59,21 @@ </includes> </fileSet> <fileSet> + <directory>${project.basedir}/src/main/scripts</directory> + <outputDirectory>/scripts</outputDirectory> + <fileMode>0755</fileMode> + <includes> + <include>get-weight.sh</include> + </includes> + </fileSet> + <fileSet> <directory>${project.basedir}</directory> <outputDirectory>/</outputDirectory> <fileMode>0600</fileMode> <includes> <include>README*</include> <include>LICENSE*</include> - <include>NOTICE*</include> + <include>INSTALL*</include> </includes> </fileSet> </fileSets> http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/bin/haproxy-extension.sh ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/bin/haproxy-extension.sh b/extensions/load-balancer/haproxy-extension/src/main/bin/haproxy-extension.sh index be1f91e..bc19205 100755 --- a/extensions/load-balancer/haproxy-extension/src/main/bin/haproxy-extension.sh +++ b/extensions/load-balancer/haproxy-extension/src/main/bin/haproxy-extension.sh @@ -21,20 +21,23 @@ # -------------------------------------------------------------- echo "Starting haproxy extension..." -lib_path=./../lib/ -class_path=`echo ../lib/*.jar | tr ' ' ':'` -properties="-Djndi.properties.dir=./../conf - -Dexecutable.file.path=/Users/imesh/dist/haproxy/haproxy-1.4.24/haproxy - -Dtemplates.path=./../templates +script_path=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)`"` +lib_path=${script_path}/../lib/ +class_path=`echo ${lib_path}/*.jar | tr ' ' ':'` +properties="-Djndi.properties.dir=${script_path}/../conf + -Dexecutable.file.path=haproxy + -Dtemplates.path=${script_path}/../templates -Dtemplates.name=haproxy.cfg.template + -Dscripts.path=${script_path}/../scripts -Dconf.file.path=/tmp/haproxy.cfg - -Dlog4j.properties.file.path=./../conf/log4j.properties - -Djavax.net.ssl.trustStore=./../security/client-truststore.jks + -Dstats.socket.file.path=/tmp/haproxy-stats.socket + -Dlog4j.properties.file.path=${script_path}/../conf/log4j.properties + -Djavax.net.ssl.trustStore=${script_path}/../security/client-truststore.jks -Djavax.net.ssl.trustStorePassword=wso2carbon -Dthrift.receiver.ip=localhost -Dthrift.receiver.port=7615" -# Uncomment below line and add $debug next to $properties to enable remote debugging +# Uncomment below line to enable remote debugging #debug="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" -java -cp "$class_path" $properties org.apache.stratos.haproxy.extension.Main -Dp1=sample_value $* +java -cp "${class_path}" ${properties} ${debug} org.apache.stratos.haproxy.extension.Main -Dp1=sample_value $* http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/CommandUtil.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/CommandUtil.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/CommandUtil.java new file mode 100644 index 0000000..7adea28 --- /dev/null +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/CommandUtil.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.stratos.haproxy.extension; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +/** + * A utility class for executing shell commands. + */ +public class CommandUtil { + private static final Log log = LogFactory.getLog(CommandUtil.class); + private static final String NEW_LINE = System.getProperty("line.separator"); + + public static String executeCommand(String command) throws IOException { + String line; + Runtime r = Runtime.getRuntime(); + if (log.isDebugEnabled()) { + log.debug("command = " + command); + } + Process p = r.exec(command); + + StringBuilder output = new StringBuilder(); + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + while ((line = in.readLine()) != null) { + if (log.isDebugEnabled()) { + log.debug("output = " + line); + } + output.append(line + NEW_LINE); + } + StringBuilder errors = new StringBuilder(); + BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream())); + while ((line = error.readLine()) != null) { + if (log.isDebugEnabled()) { + log.debug("error = " + line); + } + errors.append(line + NEW_LINE); + } + if (errors.length() > 0) { + throw new RuntimeException("Command execution failed: " + NEW_LINE + errors.toString()); + } + + return output.toString(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxy.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxy.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxy.java index dac52af..aca4ac9 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxy.java +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxy.java @@ -19,21 +19,19 @@ package org.apache.stratos.haproxy.extension; -import java.io.*; -import java.util.Vector; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.stratos.load.balancer.extension.api.LoadBalancer; import org.apache.stratos.load.balancer.extension.api.exception.LoadBalancerExtensionException; import org.apache.stratos.messaging.domain.topology.Topology; -import org.apache.stratos.load.balancer.extension.api.LoadBalancer; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.Vector; /** * HAProxy load balancer life-cycle implementation. - * <p/> - * Thanks to Vaadin for HAProxyController implementation: - * https://vaadin.com/license - * http://dev.vaadin.com/browser/svn/incubator/Arvue/ArvueMaster/src/org/vaadin/arvue/arvuemaster/HAProxyController.java */ public class HAProxy implements LoadBalancer { private static final Log log = LogFactory.getLog(HAProxy.class); @@ -44,39 +42,15 @@ public class HAProxy implements LoadBalancer { private String templatePath; private String templateName; private String confFilePath; + private String statsSocketFilePath; - public HAProxy(String executableFilePath, String templatePath, String templateName, String confFilePath) { - this.executableFilePath = executableFilePath; - this.templatePath = templatePath; - this.templateName = templateName; - this.confFilePath = confFilePath; + public HAProxy() { + this.executableFilePath = HAProxyContext.getInstance().getExecutableFilePath(); + this.templatePath = HAProxyContext.getInstance().getTemplatePath(); + this.templateName = HAProxyContext.getInstance().getTemplateName(); + this.confFilePath = HAProxyContext.getInstance().getConfFilePath(); this.processIdFilePath = confFilePath.replace(".cfg", ".pid"); - } - - private void executeCommand(String command) throws IOException { - String line; - Runtime r = Runtime.getRuntime(); - if (log.isDebugEnabled()) { - log.debug("command = " + command); - } - Process p = r.exec(command); - BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); - while ((line = in.readLine()) != null) { - if (log.isInfoEnabled()) { - log.info(line); - } - } - StringBuilder sb = new StringBuilder(); - BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream())); - while ((line = error.readLine()) != null) { - if (log.isInfoEnabled()) { - log.info(line); - sb.append(line + NEW_LINE); - } - } - if (sb.length() > 0) { - throw new RuntimeException("Command execution failed: " + NEW_LINE + sb.toString()); - } + this.statsSocketFilePath = HAProxyContext.getInstance().getStatsSocketFilePath(); } private void reloadConfiguration() throws LoadBalancerExtensionException { @@ -96,7 +70,7 @@ public class HAProxy implements LoadBalancer { // Execute hot configuration deployment String command = executableFilePath + " -f " + confFilePath + " -p " + processIdFilePath + " -sf " + pid; - executeCommand(command); + CommandUtil.executeCommand(command); if (log.isInfoEnabled()) { log.info("Configuration done"); } @@ -120,7 +94,7 @@ public class HAProxy implements LoadBalancer { log.info("Configuring haproxy instance..."); } - HAProxyConfigWriter writer = new HAProxyConfigWriter(templatePath, templateName, confFilePath); + HAProxyConfigWriter writer = new HAProxyConfigWriter(templatePath, templateName, confFilePath, statsSocketFilePath); writer.write(topology); if (log.isInfoEnabled()) { @@ -145,7 +119,7 @@ public class HAProxy implements LoadBalancer { // Start haproxy and write pid to processIdFilePath try { String command = executableFilePath + " -f " + confFilePath + " -p " + processIdFilePath; - executeCommand(command); + CommandUtil.executeCommand(command); if (log.isInfoEnabled()) { log.info("haproxy started"); } @@ -171,13 +145,13 @@ public class HAProxy implements LoadBalancer { // Kill all haproxy processes for (String pid : pids) { String command = "kill -s 9 " + pid; - executeCommand(command); + CommandUtil.executeCommand(command); if (log.isInfoEnabled()) { log.info(String.format("haproxy stopped [pid] %s", pid)); } } } catch (Exception e) { - if(log.isErrorEnabled()) { + if (log.isErrorEnabled()) { log.error("Could not stop haproxy"); } throw new LoadBalancerExtensionException(e); http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyConfigWriter.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyConfigWriter.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyConfigWriter.java index 5e6f69a..d282a76 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyConfigWriter.java +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyConfigWriter.java @@ -21,7 +21,6 @@ package org.apache.stratos.haproxy.extension; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.stratos.load.balancer.extension.api.exception.LoadBalancerExtensionException; import org.apache.stratos.messaging.domain.topology.*; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; @@ -35,11 +34,6 @@ import java.io.StringWriter; /** * HAProxy load balancer configuration writer. - * - * Thanks to Vaadin for HAProxyController implementation: - * https://vaadin.com/license - * http://dev.vaadin.com/browser/svn/incubator/Arvue/ArvueMaster/src/org/vaadin/arvue/arvuemaster/HAProxyController.java - */ public class HAProxyConfigWriter { private static final Log log = LogFactory.getLog(Main.class); @@ -48,39 +42,45 @@ public class HAProxyConfigWriter { private String templatePath; private String templateName; private String confFilePath; + private String statsSocketFilePath; - public HAProxyConfigWriter(String templatePath, String templateName, String confFilePath) { + public HAProxyConfigWriter(String templatePath, String templateName, String confFilePath, String statsSocketFilePath) { this.templatePath = templatePath; this.templateName = templateName; this.confFilePath = confFilePath; + this.statsSocketFilePath = statsSocketFilePath; } public void write(Topology topology) { - - StringBuilder sb = new StringBuilder(); - - for(Service service : topology.getServices()) { - for(Cluster cluster : service.getClusters()) { - if((service.getPorts() == null) || (service.getPorts().size() == 0)) { + // Prepare global parameters + StringBuilder globalParameters = new StringBuilder(); + globalParameters.append("stats socket "); + globalParameters.append(statsSocketFilePath); + + // Prepare frontend-backend collection + StringBuilder frontendBackendCollection = new StringBuilder(); + for (Service service : topology.getServices()) { + for (Cluster cluster : service.getClusters()) { + if ((service.getPorts() == null) || (service.getPorts().size() == 0)) { throw new RuntimeException(String.format("No ports found in service: %s", service.getServiceName())); } - for(Port port : service.getPorts()) { + for (Port port : service.getPorts()) { - String frontEndId = cluster.getClusterId() + "-proxy-" + port.getProxy(); - String backEndId = frontEndId + "-members"; + String frontendId = cluster.getClusterId() + "-proxy-" + port.getProxy(); + String backendId = frontendId + "-members"; - sb.append("frontend ").append(frontEndId).append(NEW_LINE); - sb.append("\tbind ").append(cluster.getHostName()).append(":").append(port.getProxy()).append(NEW_LINE); - sb.append("\tdefault_backend ").append(backEndId).append(NEW_LINE); - sb.append(NEW_LINE); - sb.append("backend ").append(backEndId).append(NEW_LINE); + frontendBackendCollection.append("frontend ").append(frontendId).append(NEW_LINE); + frontendBackendCollection.append("\tbind ").append(cluster.getHostName()).append(":").append(port.getProxy()).append(NEW_LINE); + frontendBackendCollection.append("\tdefault_backend ").append(backendId).append(NEW_LINE); + frontendBackendCollection.append(NEW_LINE); + frontendBackendCollection.append("backend ").append(backendId).append(NEW_LINE); for (Member member : cluster.getMembers()) { - sb.append("\tserver ").append(member.getMemberId()).append(" ") - .append(member.getMemberIp()).append(":").append(port.getValue()).append(NEW_LINE); + frontendBackendCollection.append("\tserver ").append(member.getMemberId()).append(" ") + .append(member.getMemberIp()).append(":").append(port.getValue()).append(NEW_LINE); } - sb.append(NEW_LINE); + frontendBackendCollection.append(NEW_LINE); } } } @@ -95,7 +95,8 @@ public class HAProxyConfigWriter { // Insert strings into the template VelocityContext context = new VelocityContext(); - context.put("frontend_backend_collection", sb.toString()); + context.put("global_parameters", globalParameters.toString()); + context.put("frontend_backend_collection", frontendBackendCollection.toString()); // Create a new string from the template StringWriter stringWriter = new StringWriter(); @@ -108,11 +109,11 @@ public class HAProxyConfigWriter { writer.write(configuration); writer.close(); - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info(String.format("Configuration written to file: %s", confFilePath)); } } catch (IOException e) { - if(log.isErrorEnabled()) { + if (log.isErrorEnabled()) { log.error(String.format("Could not write configuration file: %s", confFilePath)); } throw new RuntimeException(e); http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyContext.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyContext.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyContext.java new file mode 100644 index 0000000..c1c34a8 --- /dev/null +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyContext.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.stratos.haproxy.extension; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * HAProxy context to read and store system properties. + */ +public class HAProxyContext { + private static final Log log = LogFactory.getLog(HAProxyContext.class); + private static volatile HAProxyContext context; + + private String executableFilePath; + private String processIdFilePath; + private String templatePath; + private String templateName; + private String scriptsPath; + private String confFilePath; + private String statsSocketFilePath; + + private HAProxyContext() { + this.executableFilePath = System.getProperty("executable.file.path"); + this.templatePath = System.getProperty("templates.path"); + this.templateName = System.getProperty("templates.name"); + this.scriptsPath = System.getProperty("scripts.path"); + this.confFilePath = System.getProperty("conf.file.path"); + this.statsSocketFilePath = System.getProperty("stats.socket.file.path"); + + if (log.isDebugEnabled()) { + log.debug("executable.file.path = " + executableFilePath); + log.debug("templates.path = " + templatePath); + log.debug("templates.name = " + templateName); + log.debug("scripts.path = " + scriptsPath); + log.debug("conf.file.path = " + confFilePath); + log.debug("stats.socket.file.path = " + statsSocketFilePath); + } + } + + public static HAProxyContext getInstance() { + if (context == null) { + synchronized (HAProxyContext.class) { + if (context == null) { + context = new HAProxyContext(); + } + } + } + return context; + } + + public void validate() { + if ((StringUtils.isEmpty(executableFilePath)) || (StringUtils.isEmpty(templatePath)) || (StringUtils.isEmpty(templateName)) || + (StringUtils.isEmpty(scriptsPath)) || (StringUtils.isEmpty(confFilePath)) || (StringUtils.isEmpty(statsSocketFilePath))) { + throw new RuntimeException("Required system properties were not found: executable.file.path, templates.path, templates.name, scripts.path, conf.file.path, stats.socket.file.path"); + } + } + + public String getExecutableFilePath() { + return executableFilePath; + } + + public String getProcessIdFilePath() { + return processIdFilePath; + } + + public String getTemplatePath() { + return templatePath; + } + + public String getTemplateName() { + return templateName; + } + + public String getScriptsPath() { + return scriptsPath; + } + + public String getConfFilePath() { + return confFilePath; + } + + public String getStatsSocketFilePath() { + return statsSocketFilePath; + } +} http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyStatsReader.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyStatsReader.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyStatsReader.java index d76cc0b..57c6bc0 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyStatsReader.java +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/HAProxyStatsReader.java @@ -19,15 +19,78 @@ package org.apache.stratos.haproxy.extension; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.stratos.load.balancer.extension.api.LoadBalancerStatsReader; +import org.apache.stratos.messaging.domain.topology.Cluster; +import org.apache.stratos.messaging.domain.topology.Member; +import org.apache.stratos.messaging.domain.topology.Port; +import org.apache.stratos.messaging.domain.topology.Service; +import org.apache.stratos.messaging.message.receiver.topology.TopologyManager; + +import java.io.IOException; /** * HAProxy statistics reader. */ public class HAProxyStatsReader implements LoadBalancerStatsReader { + private static final Log log = LogFactory.getLog(HAProxyStatsReader.class); + + private String scriptsPath; + private String statsSocketFilePath; + + public HAProxyStatsReader() { + this.scriptsPath = HAProxyContext.getInstance().getScriptsPath(); + this.statsSocketFilePath = HAProxyContext.getInstance().getStatsSocketFilePath(); + } @Override public int getInFlightRequestCount(String clusterId) { + String frontendId, backendId, command, output; + String[] array; + int totalWeight, weight; + + for (Service service : TopologyManager.getTopology().getServices()) { + for (Cluster cluster : service.getClusters()) { + if (cluster.getClusterId().equals(clusterId)) { + totalWeight = 0; + if ((service.getPorts() == null) || (service.getPorts().size() == 0)) { + throw new RuntimeException(String.format("No ports found in service: %s", service.getServiceName())); + } + + for (Port port : service.getPorts()) { + frontendId = cluster.getClusterId() + "-proxy-" + port.getProxy(); + backendId = frontendId + "-members"; + + for (Member member : cluster.getMembers()) { + // echo "get weight <backend>/<server>" | socat stdio <stats-socket> + command = String.format("%s/get-weight.sh %s %s %s", scriptsPath, backendId, member.getMemberId(), statsSocketFilePath); + try { + output = CommandUtil.executeCommand(command); + if ((output != null) && (output.length() > 0)) { + array = output.split(" "); + if ((array != null) && (array.length > 0)) { + weight = Integer.parseInt(array[0]); + if (log.isDebugEnabled()) { + log.debug(String.format("Member weight found: [cluster] %s [member] %s [weight] %d", member.getClusterId(), member.getMemberId(), weight)); + } + totalWeight += weight; + } + } + } catch (IOException e) { + if (log.isErrorEnabled()) { + log.error(e); + } + } + } + } + if (log.isInfoEnabled()) { + log.info(String.format("Cluster weight found: [cluster] %s [weight] %d", cluster.getClusterId(), totalWeight)); + } + return totalWeight; + } + } + } return 0; } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/Main.java ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/Main.java b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/Main.java index fea9c2a..2cf1044 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/Main.java +++ b/extensions/load-balancer/haproxy-extension/src/main/java/org/apache/stratos/haproxy/extension/Main.java @@ -19,7 +19,6 @@ package org.apache.stratos.haproxy.extension; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.PropertyConfigurator; @@ -38,40 +37,20 @@ public class Main { // Configure log4j properties PropertyConfigurator.configure(System.getProperty("log4j.properties.file.path")); - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info("HAProxy extension started"); } - String executableFilePath = System.getProperty("executable.file.path"); - String templatePath = System.getProperty("templates.path"); - String templateName = System.getProperty("templates.name"); - String confFilePath = System.getProperty("conf.file.path"); - - if(log.isDebugEnabled()) { - log.debug("executable.file.path = " + executableFilePath); - log.debug("templates.path = " + templatePath); - log.debug("templates.name = " + templateName); - log.debug("conf.file.path = " + confFilePath); - } - - if((StringUtils.isEmpty(executableFilePath)) || (StringUtils.isEmpty(templatePath)) || (StringUtils.isEmpty(templateName)) || (StringUtils.isEmpty(confFilePath))) { - if(log.isErrorEnabled()) { - log.error("System properties are not valid. Expected: executable.file.path, templates.path, templates.name, conf.file.path"); - } - return; - } - - HAProxy haProxy = new HAProxy(executableFilePath, templatePath, templateName, confFilePath); - HAProxyStatsReader statsReader = new HAProxyStatsReader(); - extension = new LoadBalancerExtension(haProxy, statsReader); + // Validate rumtime parameters + HAProxyContext.getInstance().validate(); + extension = new LoadBalancerExtension(new HAProxy(), new HAProxyStatsReader()); Thread thread = new Thread(extension); thread.start(); - } - catch (Exception e) { - if(log.isErrorEnabled()) { + } catch (Exception e) { + if (log.isErrorEnabled()) { log.error(e); } - if(extension != null) { + if (extension != null) { extension.terminate(); } } http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/resources/log4j.properties ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/resources/log4j.properties b/extensions/load-balancer/haproxy-extension/src/main/resources/log4j.properties deleted file mode 100644 index 7d8a934..0000000 --- a/extensions/load-balancer/haproxy-extension/src/main/resources/log4j.properties +++ /dev/null @@ -1,37 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# Set root logger level and appenders -log4j.rootLogger=INFO, CONSOLE_APPENDER, FILE_APPENDER - -# CONSOLE_APPENDER is set to be a ConsoleAppender. -log4j.appender.CONSOLE_APPENDER=org.apache.log4j.ConsoleAppender - -# The standard error log where all the warnings, errors and fatal errors will be logged -log4j.appender.FILE_APPENDER=org.apache.log4j.FileAppender -log4j.appender.FILE_APPENDER.File=log/haproxy-extension.log -log4j.appender.FILE_APPENDER.layout=org.apache.log4j.PatternLayout -log4j.appender.FILE_APPENDER.layout.ConversionPattern=%d{ISO8601} [%X{ip}-%X{host}] [%t] %5p %c{1} %m%n -log4j.appender.FILE_APPENDER.threshold=DEBUG - -# CONSOLE_APPENDER uses PatternLayout. -log4j.appender.CONSOLE_APPENDER.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE_APPENDER.layout.ConversionPattern=[%d{ISO8601}] %5p - [%c{1}] %m%n - -log4j.logger.org.apache.stratos.haproxy.extension=TRACE \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/scripts/get-weight.sh ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/scripts/get-weight.sh b/extensions/load-balancer/haproxy-extension/src/main/scripts/get-weight.sh new file mode 100644 index 0000000..cef3a1f --- /dev/null +++ b/extensions/load-balancer/haproxy-extension/src/main/scripts/get-weight.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# -------------------------------------------------------------- +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# -------------------------------------------------------------- + +echo "get weight $1/$2" | socat stdio $3 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/5d8ab42f/extensions/load-balancer/haproxy-extension/src/main/templates/haproxy.cfg.template ---------------------------------------------------------------------- diff --git a/extensions/load-balancer/haproxy-extension/src/main/templates/haproxy.cfg.template b/extensions/load-balancer/haproxy-extension/src/main/templates/haproxy.cfg.template index 240f64a..c58ce87 100644 --- a/extensions/load-balancer/haproxy-extension/src/main/templates/haproxy.cfg.template +++ b/extensions/load-balancer/haproxy-extension/src/main/templates/haproxy.cfg.template @@ -1,7 +1,7 @@ global daemon maxconn 256 - stats socket /tmp/haproxy_stats + $global_parameters defaults mode http
