mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
Merge branch 'fixloadbalancer2'
This commit is contained in:
commit
1597671e73
@ -26,11 +26,12 @@ import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
public class LoadBalancerConfigCommand extends RoutingCommand {
|
||||
LoadBalancerTO[] loadBalancers;
|
||||
|
||||
public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers) {
|
||||
public LoadBalancerConfigCommand( LoadBalancerTO[] loadBalancers) {
|
||||
this.loadBalancers = loadBalancers;
|
||||
}
|
||||
|
||||
public LoadBalancerTO[] getLoadBalancers() {
|
||||
|
||||
public LoadBalancerTO[] getLoadBalancers() {
|
||||
return loadBalancers;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,11 +49,18 @@ import com.cloud.agent.api.routing.IPAssocCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocAnswer;
|
||||
import com.cloud.agent.api.routing.LoadBalancerCfgCommand;
|
||||
import com.cloud.agent.api.routing.RoutingCommand;
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.routing.SavePasswordCommand;
|
||||
import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
|
||||
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
|
||||
import com.cloud.agent.api.routing.VmDataCommand;
|
||||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.api.to.PortForwardingRuleTO;
|
||||
import com.cloud.network.HAProxyConfigurator;
|
||||
import com.cloud.network.LoadBalancerConfigurator;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.utils.script.OutputInterpreter;
|
||||
import com.cloud.utils.script.Script;
|
||||
|
||||
@ -89,11 +96,12 @@ public class VirtualRoutingResource implements Manager {
|
||||
|
||||
public Answer executeRequest(final Command cmd) {
|
||||
try {
|
||||
// if (cmd instanceof SetFirewallRuleCommand) {
|
||||
// return execute((SetFirewallRuleCommand)cmd);
|
||||
// }else
|
||||
if (cmd instanceof LoadBalancerCfgCommand) {
|
||||
if (cmd instanceof SetPortForwardingRulesCommand ) {
|
||||
return execute((SetPortForwardingRulesCommand)cmd);
|
||||
}else if (cmd instanceof LoadBalancerCfgCommand) {
|
||||
return execute((LoadBalancerCfgCommand)cmd);
|
||||
} else if (cmd instanceof LoadBalancerConfigCommand) {
|
||||
return execute((LoadBalancerConfigCommand)cmd);
|
||||
} else if (cmd instanceof IPAssocCommand) {
|
||||
return execute((IPAssocCommand)cmd);
|
||||
} else if (cmd instanceof CheckConsoleProxyLoadCommand) {
|
||||
@ -114,7 +122,66 @@ public class VirtualRoutingResource implements Manager {
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(VmDataCommand cmd) {
|
||||
private Answer execute(SetPortForwardingRulesCommand cmd) {
|
||||
String routerIp = cmd.getAccessDetail(RoutingCommand.ROUTER_IP);
|
||||
String routerName = cmd.getAccessDetail(RoutingCommand.ROUTER_NAME);
|
||||
|
||||
String[] results = new String[cmd.getRules().length];
|
||||
int i = 0;
|
||||
for (PortForwardingRuleTO rule : cmd.getRules()) {
|
||||
String result = null;
|
||||
if (rule.getProtocol().equalsIgnoreCase(NetUtils.NAT_PROTO)){
|
||||
setStaticNat(!rule.revoked(), routerName, routerIp, rule.getSrcIp(), rule.getDstIp());
|
||||
} else {
|
||||
|
||||
result = setPortForwardRule(!rule.revoked(), routerName, routerIp,
|
||||
rule.getProtocol(), rule.getSrcIp(),
|
||||
Integer.toString(rule.getSrcPortRange()[0]), rule.getDstIp(),
|
||||
Integer.toString(rule.getDstPortRange()[0]));
|
||||
|
||||
}
|
||||
results[i++] = (result == null || result.isEmpty()) ? "Failed" : null;
|
||||
}
|
||||
|
||||
return new SetPortForwardingRulesAnswer(cmd, results);
|
||||
}
|
||||
|
||||
private Answer execute(LoadBalancerConfigCommand cmd) {
|
||||
String routerIp = cmd.getAccessDetail(RoutingCommand.ROUTER_IP);
|
||||
File tmpCfgFile = null;
|
||||
try {
|
||||
String cfgFilePath = "";
|
||||
String routerIP = null;
|
||||
LoadBalancerConfigurator cfgtr = new HAProxyConfigurator();
|
||||
String[] config = cfgtr.generateConfiguration(cmd);
|
||||
String[][] rules = cfgtr.generateFwRules(cmd);
|
||||
if (routerIp != null) {
|
||||
tmpCfgFile = File.createTempFile(routerIp.replace('.', '_'), "cfg");
|
||||
final PrintWriter out
|
||||
= new PrintWriter(new BufferedWriter(new FileWriter(tmpCfgFile)));
|
||||
for (int i=0; i < config.length; i++) {
|
||||
out.println(config[i]);
|
||||
}
|
||||
out.close();
|
||||
cfgFilePath = tmpCfgFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
final String result = setLoadBalancerConfig(cfgFilePath,
|
||||
rules[LoadBalancerConfigurator.ADD],
|
||||
rules[LoadBalancerConfigurator.REMOVE],
|
||||
routerIP);
|
||||
|
||||
return new Answer(cmd, result == null, result);
|
||||
} catch (final IOException e) {
|
||||
return new Answer(cmd, false, e.getMessage());
|
||||
} finally {
|
||||
if (tmpCfgFile != null) {
|
||||
tmpCfgFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Answer execute(VmDataCommand cmd) {
|
||||
List<String[]> vmData = cmd.getVmData();
|
||||
|
||||
for (String[] vmDataEntry : vmData) {
|
||||
@ -381,39 +448,47 @@ public class VirtualRoutingResource implements Manager {
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
public String setFirewallRules(final boolean enable, final String routerName, final String routerIpAddress, final String protocol,
|
||||
final String publicIpAddress, final String publicPort, final String privateIpAddress, final String privatePort,
|
||||
String oldPrivateIP, String oldPrivatePort, String vlanNetmask) {
|
||||
public String setPortForwardRule(final boolean enable, final String routerName, final String routerIpAddress, final String protocol,
|
||||
final String publicIpAddress, final String publicPortRange, final String privateIpAddress, final String privatePortRange) {
|
||||
|
||||
if (routerIpAddress == null) {
|
||||
s_logger.warn("SetFirewallRuleCommand did nothing because Router IP address was null when creating rule for public IP: " + publicIpAddress);
|
||||
s_logger.warn("setPortForwardRule did nothing because Router IP address was null when creating rule for public IP: " + publicIpAddress);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (oldPrivateIP == null) {
|
||||
oldPrivateIP = "";
|
||||
}
|
||||
if (oldPrivatePort == null) {
|
||||
oldPrivatePort = "";
|
||||
}
|
||||
|
||||
|
||||
final Script command = new Script(_firewallPath, _timeout, s_logger);
|
||||
|
||||
command.add(enable ? "-A" : "-D");
|
||||
command.add("-P", protocol);
|
||||
command.add("-l", publicIpAddress);
|
||||
command.add("-p", publicPort);
|
||||
command.add("-p", publicPortRange);
|
||||
command.add("-n", routerName);
|
||||
command.add("-i", routerIpAddress);
|
||||
command.add("-r", privateIpAddress);
|
||||
command.add("-d", privatePort);
|
||||
command.add("-N", vlanNetmask);
|
||||
command.add("-w", oldPrivateIP);
|
||||
command.add("-x", oldPrivatePort);
|
||||
command.add("-d", privatePortRange);
|
||||
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
public String setStaticNat(final boolean enable, final String routerName, final String routerIpAddress,
|
||||
final String publicIpAddress, final String privateIpAddress) {
|
||||
|
||||
if (routerIpAddress == null) {
|
||||
s_logger.warn("setStaticNat did nothing because Router IP address was null when creating rule for public IP: " + publicIpAddress);
|
||||
return null;
|
||||
}
|
||||
|
||||
final Script command = new Script(_firewallPath, _timeout, s_logger);
|
||||
|
||||
command.add(enable ? "-A" : "-D");
|
||||
command.add("-l", publicIpAddress);
|
||||
command.add("-n", routerName);
|
||||
command.add("-i", routerIpAddress);
|
||||
command.add("-G", privateIpAddress);
|
||||
return command.execute();
|
||||
}
|
||||
|
||||
private boolean isBridgeExists(String bridgeName) {
|
||||
Script command = new Script("/bin/sh", _timeout);
|
||||
command.add("-c");
|
||||
|
||||
@ -125,6 +125,7 @@ import com.cloud.agent.api.routing.DhcpEntryCommand;
|
||||
import com.cloud.agent.api.routing.IPAssocCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocAnswer;
|
||||
import com.cloud.agent.api.routing.LoadBalancerCfgCommand;
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
|
||||
import com.cloud.agent.api.routing.RoutingCommand;
|
||||
import com.cloud.agent.api.routing.SavePasswordCommand;
|
||||
@ -153,6 +154,8 @@ import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.HAProxyConfigurator;
|
||||
import com.cloud.network.LoadBalancerConfigurator;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.resource.ServerResource;
|
||||
@ -349,6 +352,8 @@ public abstract class CitrixResourceBase implements ServerResource {
|
||||
return execute((SetPortForwardingRulesCommand) cmd);
|
||||
} else if (cmd instanceof LoadBalancerCfgCommand) {
|
||||
return execute((LoadBalancerCfgCommand) cmd);
|
||||
} else if (cmd instanceof LoadBalancerConfigCommand) {
|
||||
return execute((LoadBalancerConfigCommand) cmd);
|
||||
} else if (cmd instanceof IPAssocCommand) {
|
||||
return execute((IPAssocCommand) cmd);
|
||||
} else if (cmd instanceof CheckConsoleProxyLoadCommand) {
|
||||
@ -1032,6 +1037,66 @@ public abstract class CitrixResourceBase implements ServerResource {
|
||||
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
protected Answer execute(final LoadBalancerConfigCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
String routerIp = cmd.getAccessDetail(RoutingCommand.ROUTER_IP);
|
||||
|
||||
if (routerIp == null) {
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
LoadBalancerConfigurator cfgtr = new HAProxyConfigurator();
|
||||
String[] config = cfgtr.generateConfiguration(cmd);
|
||||
String[][] rules = cfgtr.generateFwRules(cmd);
|
||||
String tmpCfgFilePath = "/tmp/" + routerIp.replace('.', '_') + ".cfg";
|
||||
String tmpCfgFileContents = "";
|
||||
for (int i = 0; i < config.length; i++) {
|
||||
tmpCfgFileContents += config[i];
|
||||
tmpCfgFileContents += "\n";
|
||||
}
|
||||
|
||||
String result = callHostPlugin(conn, "vmops", "createFile", "filepath", tmpCfgFilePath, "filecontents", tmpCfgFileContents);
|
||||
|
||||
if (result == null || result.isEmpty()) {
|
||||
return new Answer(cmd, false, "LoadBalancerConfigCommand failed to create HA proxy cfg file.");
|
||||
}
|
||||
|
||||
String[] addRules = rules[LoadBalancerConfigurator.ADD];
|
||||
String[] removeRules = rules[LoadBalancerConfigurator.REMOVE];
|
||||
|
||||
String args = "";
|
||||
args += "-i " + routerIp;
|
||||
args += " -f " + tmpCfgFilePath;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (addRules.length > 0) {
|
||||
for (int i = 0; i < addRules.length; i++) {
|
||||
sb.append(addRules[i]).append(',');
|
||||
}
|
||||
|
||||
args += " -a " + sb.toString();
|
||||
}
|
||||
|
||||
sb = new StringBuilder();
|
||||
if (removeRules.length > 0) {
|
||||
for (int i = 0; i < removeRules.length; i++) {
|
||||
sb.append(removeRules[i]).append(',');
|
||||
}
|
||||
|
||||
args += " -d " + sb.toString();
|
||||
}
|
||||
|
||||
result = callHostPlugin(conn, "vmops", "setLoadBalancerRule", "args", args);
|
||||
|
||||
if (result == null || result.isEmpty()) {
|
||||
return new Answer(cmd, false, "LoadBalancerConfigCommand failed");
|
||||
}
|
||||
|
||||
callHostPlugin(conn, "vmops", "deleteFile", "filepath", tmpCfgFilePath);
|
||||
|
||||
return new Answer(cmd);
|
||||
}
|
||||
|
||||
protected synchronized Answer execute(final DhcpEntryCommand cmd) {
|
||||
Connection conn = getConnection();
|
||||
|
||||
@ -25,7 +25,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO;
|
||||
import com.cloud.agent.api.to.PortForwardingRuleTO;
|
||||
import com.cloud.agent.api.to.LoadBalancerTO.DestinationTO;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
|
||||
@ -143,6 +146,47 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
|
||||
result.add(getBlankLine());
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> getRulesForPool(LoadBalancerTO lbTO) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String poolName = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString();
|
||||
String publicIP = lbTO.getSrcIp();
|
||||
String publicPort = Integer.toString(lbTO.getSrcPort());
|
||||
String algorithm = lbTO.getAlgorithm();
|
||||
|
||||
List<String> result = new ArrayList<String>();
|
||||
//add line like this: "listen 65_37_141_30-80 65.37.141.30:80"
|
||||
sb = new StringBuilder();
|
||||
sb.append("listen ").append(poolName).append(" ")
|
||||
.append(publicIP).append(":").append(publicPort);
|
||||
result.add(sb.toString());
|
||||
sb = new StringBuilder();
|
||||
sb.append("\t").append("balance ").append(algorithm);
|
||||
result.add(sb.toString());
|
||||
if (publicPort.equals(NetUtils.HTTP_PORT)) {
|
||||
sb = new StringBuilder();
|
||||
sb.append("\t").append("mode http");
|
||||
result.add(sb.toString());
|
||||
sb = new StringBuilder();
|
||||
sb.append("\t").append("option httpclose");
|
||||
result.add(sb.toString());
|
||||
}
|
||||
int i=0;
|
||||
for (DestinationTO dest: lbTO.getDestinations()) {
|
||||
//add line like this: "server 65_37_141_30-80_3 10.1.1.4:80 check"
|
||||
if (dest.isRevoked()) {
|
||||
continue;
|
||||
}
|
||||
sb = new StringBuilder();
|
||||
sb.append("\t").append("server ").append(poolName)
|
||||
.append("_").append(Integer.toString(i++)).append(" ")
|
||||
.append(dest.getDestIp()).append(":").append(dest.getDestPort())
|
||||
.append(" check");
|
||||
result.add(sb.toString());
|
||||
}
|
||||
result.add(getBlankLine());
|
||||
return result;
|
||||
}
|
||||
|
||||
private String getBlankLine() {
|
||||
return new String("\t ");
|
||||
@ -176,4 +220,53 @@ public class HAProxyConfigurator implements LoadBalancerConfigurator {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] generateConfiguration(LoadBalancerConfigCommand lbCmd) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
|
||||
result.addAll(Arrays.asList(globalSection));
|
||||
result.add(getBlankLine());
|
||||
result.addAll(Arrays.asList(defaultsSection));
|
||||
result.add(getBlankLine());
|
||||
|
||||
if (lbCmd.getLoadBalancers().length == 0){
|
||||
//haproxy cannot handle empty listen / frontend or backend, so add a dummy listener
|
||||
//on port 9
|
||||
result.addAll(Arrays.asList(defaultListen));
|
||||
}
|
||||
result.add(getBlankLine());
|
||||
|
||||
for (LoadBalancerTO lbTO: lbCmd.getLoadBalancers()){
|
||||
List<String> poolRules = getRulesForPool(lbTO);
|
||||
result.addAll(poolRules);
|
||||
}
|
||||
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[][] generateFwRules(LoadBalancerConfigCommand lbCmd) {
|
||||
String [][] result = new String [2][];
|
||||
Set<String> toAdd = new HashSet<String>();
|
||||
Set<String> toRemove = new HashSet<String>();
|
||||
|
||||
for (LoadBalancerTO lbTO: lbCmd.getLoadBalancers()) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(lbTO.getSrcIp()).append(":");
|
||||
sb.append(lbTO.getSrcPort()).append(":");
|
||||
String lbRuleEntry = sb.toString();
|
||||
if (!lbTO.isRevoked()) {
|
||||
toAdd.add(lbRuleEntry);
|
||||
} else {
|
||||
toRemove.add(lbRuleEntry);
|
||||
}
|
||||
}
|
||||
toRemove.removeAll(toAdd);
|
||||
result[ADD] = toAdd.toArray(new String[toAdd.size()]);
|
||||
result[REMOVE] = toRemove.toArray(new String[toRemove.size()]);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -19,6 +19,7 @@ package com.cloud.network;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.to.PortForwardingRuleTO;
|
||||
|
||||
|
||||
@ -32,4 +33,7 @@ public interface LoadBalancerConfigurator {
|
||||
|
||||
public String [] generateConfiguration(List<PortForwardingRuleTO> fwRules);
|
||||
public String [][] generateFwRules(List<PortForwardingRuleTO> fwRules);
|
||||
|
||||
public String [] generateConfiguration(LoadBalancerConfigCommand lbCmd);
|
||||
public String [][] generateFwRules(LoadBalancerConfigCommand lbCmd);
|
||||
}
|
||||
|
||||
@ -2099,8 +2099,16 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute
|
||||
|
||||
@Override
|
||||
public boolean applyLBRules(Network network, List<? extends FirewallRule> rules) {
|
||||
DomainRouterVO router = _routerDao.findByNetworkConfiguration(network.getId());
|
||||
if (router == null) {
|
||||
s_logger.warn("Unable to apply lb rules, virtual router doesn't exist in the network " + network.getId());
|
||||
throw new ResourceUnavailableException("Unable to apply lb rules");
|
||||
}
|
||||
|
||||
String routerControlIpAddress = router.getPrivateIpAddress();
|
||||
|
||||
DomainRouterVO router = _routerDao.findByNetworkConfiguration(network.getId());
|
||||
if (router.getState() == State.Running || router.getState() == State.Starting) {
|
||||
|
||||
Commands cmds = new Commands(OnError.Continue);
|
||||
LoadBalancerTO[] lbs = new LoadBalancerTO[rules.size()];
|
||||
int i = 0;
|
||||
@ -2124,6 +2132,14 @@ public class DomainRouterManagerImpl implements DomainRouterManager, DomainRoute
|
||||
//Send commands to router
|
||||
return sendCommandsToRouter(router, cmds);
|
||||
|
||||
} else if (router.getState() == State.Stopped || router.getState() == State.Stopping){
|
||||
s_logger.debug("Router is in " + router.getState() + ", so not sending apply LB rules commands to the backend");
|
||||
return true;
|
||||
} else {
|
||||
s_logger.warn("Unable to apply load balancer rules, virtual router is not in the right state " + router.getState());
|
||||
throw new ResourceUnavailableException("Unable to apply load balancer rules, domR is not in right state " + router.getState());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user