Skip to content

Commit 6e81098

Browse files
authored
HAProxy Configuration: network.loadbalancer.haproxy.idle.timeout (#12586)
* initial attempt at network.loadbalancer.haproxy.idle.timeout implementation * implement test cases * move idleTimeout configuration test to its own test case
1 parent e0fe953 commit 6e81098

File tree

12 files changed

+105
-15
lines changed

12 files changed

+105
-15
lines changed

core/src/main/java/com/cloud/agent/api/routing/LoadBalancerConfigCommand.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class LoadBalancerConfigCommand extends NetworkElementCommand {
3636
public String lbStatsAuth = "admin1:AdMiN123";
3737
public String lbStatsUri = "/admin?stats";
3838
public String maxconn = "";
39+
public Long idleTimeout = 50000L; /* 0=infinite, >0 = timeout in milliseconds */
3940
public String lbProtocol;
4041
public boolean keepAliveEnabled = false;
4142
NicTO nic;
@@ -50,7 +51,7 @@ public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers, Long vpcId) {
5051
}
5152

5253
public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers, String publicIp, String guestIp, String privateIp, NicTO nic, Long vpcId, String maxconn,
53-
boolean keepAliveEnabled) {
54+
boolean keepAliveEnabled, Long idleTimeout) {
5455
this.loadBalancers = loadBalancers;
5556
this.lbStatsPublicIP = publicIp;
5657
this.lbStatsPrivateIP = privateIp;
@@ -59,6 +60,7 @@ public LoadBalancerConfigCommand(LoadBalancerTO[] loadBalancers, String publicIp
5960
this.vpcId = vpcId;
6061
this.maxconn = maxconn;
6162
this.keepAliveEnabled = keepAliveEnabled;
63+
this.idleTimeout = idleTimeout;
6264
}
6365

6466
public NicTO getNic() {

core/src/main/java/com/cloud/network/HAProxyConfigurator.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,19 @@ public String[] generateConfiguration(final LoadBalancerConfigCommand lbCmd) {
638638
if (lbCmd.keepAliveEnabled) {
639639
dSection.set(7, "\tno option httpclose");
640640
}
641+
if (lbCmd.idleTimeout > 0) {
642+
dSection.set(9, "\ttimeout client " + Long.toString(lbCmd.idleTimeout));
643+
dSection.set(10, "\ttimeout server " + Long.toString(lbCmd.idleTimeout));
644+
} else if (lbCmd.idleTimeout == 0) {
645+
// .remove() is not allowed, only .set() operations are allowed as the list
646+
// is a fixed size. So lets just mark the entry as blank.
647+
dSection.set(9, "");
648+
dSection.set(10, "");
649+
} else {
650+
// Negative idleTimeout values are considered invalid; retain the
651+
// default HAProxy timeout values from defaultsSection for predictability.
652+
logger.warn("Negative idleTimeout ({}) configured; retaining default HAProxy timeouts.", lbCmd.idleTimeout);
653+
}
641654

642655
if (logger.isDebugEnabled()) {
643656
for (final String s : dSection) {

core/src/test/java/com/cloud/agent/resource/virtualnetwork/ConfigHelperTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ protected LoadBalancerConfigCommand generateLoadBalancerConfigCommand() {
235235
lbs.toArray(arrayLbs);
236236

237237
final NicTO nic = new NicTO();
238-
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, null, "1000", false);
238+
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, null, "1000", false, 0L);
239239
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, "10.1.10.2");
240240
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME);
241241

core/src/test/java/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ protected LoadBalancerConfigCommand generateLoadBalancerConfigCommand1() {
783783
final LoadBalancerTO[] arrayLbs = new LoadBalancerTO[lbs.size()];
784784
lbs.toArray(arrayLbs);
785785
final NicTO nic = new NicTO();
786-
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, null, "1000", false);
786+
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, null, "1000", false, 50000L);
787787
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, "10.1.10.2");
788788
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME);
789789
return cmd;
@@ -799,7 +799,7 @@ protected LoadBalancerConfigCommand generateLoadBalancerConfigCommand2() {
799799
lbs.toArray(arrayLbs);
800800
final NicTO nic = new NicTO();
801801
nic.setIp("10.1.10.2");
802-
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, Long.valueOf(1), "1000", false);
802+
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(arrayLbs, "64.10.2.10", "10.1.10.2", "192.168.1.2", nic, Long.valueOf(1), "1000", false, 50000L);
803803
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, "10.1.10.2");
804804
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, ROUTERNAME);
805805
return cmd;

core/src/test/java/com/cloud/network/HAProxyConfiguratorTest.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,42 @@ public void testGenerateConfigurationLoadBalancerConfigCommand() {
7979
LoadBalancerTO[] lba = new LoadBalancerTO[1];
8080
lba[0] = lb;
8181
HAProxyConfigurator hpg = new HAProxyConfigurator();
82-
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false);
82+
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false, 0L);
8383
String result = genConfig(hpg, cmd);
8484
assertTrue("keepalive disabled should result in 'option httpclose' in the resulting haproxy config", result.contains("\toption httpclose"));
8585

86-
cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "4", true);
86+
cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "4", true, 0L);
8787
result = genConfig(hpg, cmd);
8888
assertTrue("keepalive enabled should result in 'no option httpclose' in the resulting haproxy config", result.contains("\tno option httpclose"));
89+
8990
// TODO
9091
// create lb command
9192
// setup tests for
9293
// maxconn (test for maxpipes as well)
9394
// httpmode
9495
}
9596

97+
/**
98+
* Test method for {@link com.cloud.network.HAProxyConfigurator#generateConfiguration(com.cloud.agent.api.routing.LoadBalancerConfigCommand)}.
99+
*/
100+
@Test
101+
public void testGenerateConfigurationLoadBalancerIdleTimeoutConfigCommand() {
102+
LoadBalancerTO lb = new LoadBalancerTO("1", "10.2.0.1", 80, "http", "bla", false, false, false, null);
103+
LoadBalancerTO[] lba = new LoadBalancerTO[1];
104+
lba[0] = lb;
105+
HAProxyConfigurator hpg = new HAProxyConfigurator();
106+
107+
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "4", true, 0L);
108+
String result = genConfig(hpg, cmd);
109+
assertTrue("idleTimeout of 0 should not generate 'timeout server' in the resulting haproxy config", !result.contains("\ttimeout server"));
110+
assertTrue("idleTimeout of 0 should not generate 'timeout client' in the resulting haproxy config", !result.contains("\ttimeout client"));
111+
112+
cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "4", true, 1234L);
113+
result = genConfig(hpg, cmd);
114+
assertTrue("idleTimeout of 1234 should result in 'timeout server 1234' in the resulting haproxy config", result.contains("\ttimeout server 1234"));
115+
assertTrue("idleTimeout of 1234 should result in 'timeout client 1234' in the resulting haproxy config", result.contains("\ttimeout client 1234"));
116+
}
117+
96118
/**
97119
* Test method for {@link com.cloud.network.HAProxyConfigurator#generateConfiguration(com.cloud.agent.api.routing.LoadBalancerConfigCommand)}.
98120
*/
@@ -106,7 +128,7 @@ public void testGenerateConfigurationLoadBalancerProxyProtocolConfigCommand() {
106128
LoadBalancerTO[] lba = new LoadBalancerTO[1];
107129
lba[0] = lb;
108130
HAProxyConfigurator hpg = new HAProxyConfigurator();
109-
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false);
131+
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false, 0L);
110132
String result = genConfig(hpg, cmd);
111133
assertTrue("'send-proxy' should result if protocol is 'tcp-proxy'", result.contains("send-proxy"));
112134
}
@@ -118,7 +140,7 @@ public void generateConfigurationTestWithCidrList() {
118140
LoadBalancerTO[] lba = new LoadBalancerTO[1];
119141
lba[0] = lb;
120142
HAProxyConfigurator hpg = new HAProxyConfigurator();
121-
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false);
143+
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false, 0L);
122144
String result = genConfig(hpg, cmd);
123145
Assert.assertTrue(result.contains("acl network_allowed src 1.1.1.1 2.2.2.2/24 \n\ttcp-request connection reject if !network_allowed"));
124146
}
@@ -131,7 +153,7 @@ public void generateConfigurationTestWithSslCert() {
131153
LoadBalancerTO[] lba = new LoadBalancerTO[1];
132154
lba[0] = lb;
133155
HAProxyConfigurator hpg = new HAProxyConfigurator();
134-
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false);
156+
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lba, "10.0.0.1", "10.1.0.1", "10.1.1.1", null, 1L, "12", false, 0L);
135157
String result = genConfig(hpg, cmd);
136158
Assert.assertTrue(result.contains("bind 10.2.0.1:443 ssl crt /etc/cloudstack/ssl/10_2_0_1-443.pem"));
137159
}

engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/NetworkOrchestrationService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,14 @@ public interface NetworkOrchestrationService {
122122
"Load Balancer(haproxy) maximum number of concurrent connections(global max)",
123123
true,
124124
Scope.Global);
125+
ConfigKey<Long> NETWORK_LB_HAPROXY_IDLE_TIMEOUT = new ConfigKey<>(
126+
"Network",
127+
Long.class,
128+
"network.loadbalancer.haproxy.idle.timeout",
129+
"50000",
130+
"Load Balancer(haproxy) idle timeout in milliseconds. Use 0 for infinite.",
131+
true,
132+
Scope.Global);
125133

126134
List<? extends Network> setupNetwork(Account owner, NetworkOffering offering, DeploymentPlan plan, String name, String displayText, boolean isDefault)
127135
throws ConcurrentOperationException;

engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4940,6 +4940,7 @@ public ConfigKey<?>[] getConfigKeys() {
49404940
return new ConfigKey<?>[]{NetworkGcWait, NetworkGcInterval, NetworkLockTimeout, DeniedRoutes,
49414941
GuestDomainSuffix, NetworkThrottlingRate, MinVRVersion,
49424942
PromiscuousMode, MacAddressChanges, ForgedTransmits, MacLearning, RollingRestartEnabled,
4943-
TUNGSTEN_ENABLED, NSX_ENABLED, NETRIS_ENABLED, NETWORK_LB_HAPROXY_MAX_CONN};
4943+
TUNGSTEN_ENABLED, NSX_ENABLED, NETRIS_ENABLED, NETWORK_LB_HAPROXY_MAX_CONN,
4944+
NETWORK_LB_HAPROXY_IDLE_TIMEOUT};
49444945
}
49454946
}

plugins/network-elements/elastic-loadbalancer/src/main/java/com/cloud/network/lb/ElasticLoadBalancerManagerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ private void createApplyLoadBalancingRulesCommands(List<LoadBalancingRule> rules
214214
maxconn = offering.getConcurrentConnections().toString();
215215
}
216216
LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs, elbVm.getPublicIpAddress(), _nicDao.getIpAddress(guestNetworkId, elbVm.getId()),
217-
elbVm.getPrivateIpAddress(), null, null, maxconn, offering.isKeepAliveEnabled());
217+
elbVm.getPrivateIpAddress(), null, null, maxconn, offering.isKeepAliveEnabled(),
218+
NetworkOrchestrationService.NETWORK_LB_HAPROXY_IDLE_TIMEOUT.value());
218219
cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, elbVm.getPrivateIpAddress());
219220
cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, elbVm.getInstanceName());
220221
//FIXME: why are we setting attributes directly? Ick!! There should be accessors and

plugins/network-elements/internal-loadbalancer/src/main/java/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,8 @@ private void createApplyLoadBalancingRulesCommands(final List<LoadBalancingRule>
513513
}
514514
final LoadBalancerConfigCommand cmd =
515515
new LoadBalancerConfigCommand(lbs, guestNic.getIPv4Address(), guestNic.getIPv4Address(), internalLbVm.getPrivateIpAddress(), _itMgr.toNicTO(guestNicProfile,
516-
internalLbVm.getHypervisorType()), internalLbVm.getVpcId(), maxconn, offering.isKeepAliveEnabled());
516+
internalLbVm.getHypervisorType()), internalLbVm.getVpcId(), maxconn, offering.isKeepAliveEnabled(),
517+
NetworkOrchestrationService.NETWORK_LB_HAPROXY_IDLE_TIMEOUT.value());
517518

518519
cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
519520
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());

server/src/main/java/com/cloud/network/router/CommandSetupHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ public void createApplyLoadBalancingRulesCommands(final List<LoadBalancingRule>
396396
}
397397

398398
final LoadBalancerConfigCommand cmd = new LoadBalancerConfigCommand(lbs, routerPublicIp, _routerControlHelper.getRouterIpInNetwork(guestNetworkId, router.getId()),
399-
router.getPrivateIpAddress(), _itMgr.toNicTO(nicProfile, router.getHypervisorType()), router.getVpcId(), maxconn, offering.isKeepAliveEnabled());
399+
router.getPrivateIpAddress(), _itMgr.toNicTO(nicProfile, router.getHypervisorType()), router.getVpcId(), maxconn, offering.isKeepAliveEnabled(),
400+
NetworkOrchestrationService.NETWORK_LB_HAPROXY_IDLE_TIMEOUT.value());
400401

401402
cmd.lbStatsVisibility = _configDao.getValue(Config.NetworkLBHaproxyStatsVisbility.key());
402403
cmd.lbStatsUri = _configDao.getValue(Config.NetworkLBHaproxyStatsUri.key());

0 commit comments

Comments
 (0)