mirror of https://github.com/apache/cloudstack.git
Summary: Initial commit for vpc multi-network public loadbalancer
Detail: Adjust vpc_loadbalance.sh to adjust firewall rules for multi-tier LB, call /root/reconfigLB_vpc rather than /root/reconfigLB.sh (single isolatednet script). Disable check that only allows one loadbalanced network offering per VPC. BUG-ID: CLOUDSTACK-2367 Signed-off-by: Marcus Sorensen <marcus@betterservers.com> 1367957466 -0600
This commit is contained in:
parent
732566e703
commit
269e87591e
|
|
@ -54,8 +54,8 @@ fw_remove() {
|
|||
|
||||
fw_backup() {
|
||||
fw_remove_backup
|
||||
sudo iptables -E load_balancer back_load_balancer 2> /dev/null
|
||||
sudo iptables -E lb_stats back_lb_stats 2> /dev/null
|
||||
iptables -S load_balancer | sed 's/load_balancer/back_load_balancer/g'|xargs -i /bin/bash -c "/sbin/iptables {} 2>/dev/null"
|
||||
iptables -S lb_stats | sed 's/lb_stats/back_lb_stats/g'|xargs -i /bin/bash -c "/sbin/iptables {} 2>/dev/null"
|
||||
}
|
||||
|
||||
fw_restore() {
|
||||
|
|
@ -65,7 +65,6 @@ fw_restore() {
|
|||
}
|
||||
|
||||
fw_chain_create () {
|
||||
fw_backup
|
||||
sudo iptables -N load_balancer 2> /dev/null
|
||||
sudo iptables -A INPUT -p tcp -j load_balancer 2> /dev/null
|
||||
sudo iptables -N lb_stats 2> /dev/null
|
||||
|
|
@ -87,26 +86,45 @@ fw_entry() {
|
|||
fi
|
||||
local a=$(echo $added | cut -d, -f1- --output-delimiter=" ")
|
||||
local r=$(echo $removed | cut -d, -f1- --output-delimiter=" ")
|
||||
fw_chain_create
|
||||
fw_backup
|
||||
sudo iptables -L load_balancer >/dev/null 2>&1 || fw_chain_create
|
||||
success=0
|
||||
while [ 1 ]
|
||||
do
|
||||
for i in $a
|
||||
do
|
||||
local pubIp=$(echo $i | cut -d: -f1)
|
||||
local dport=$(echo $i | cut -d: -f2)
|
||||
sudo iptables -A load_balancer -p tcp -d $pubIp --dport $dport -j ACL_INBOUND_$dev 2>/dev/null
|
||||
success=$?
|
||||
if [ $success -gt 0 ]
|
||||
local dport=$(echo $i | cut -d: -f2)
|
||||
if ! sudo iptables -C load_balancer -p tcp -d $pubIp --dport $dport -j ACL_INBOUND_$dev 2>/dev/null
|
||||
then
|
||||
break
|
||||
sudo iptables -A load_balancer -p tcp -d $pubIp --dport $dport -j ACL_INBOUND_$dev 2>/dev/null
|
||||
success=$?
|
||||
if [ $success -gt 0 ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
for i in $r
|
||||
do
|
||||
local pubIp=$(echo $i | cut -d: -f1)
|
||||
local dport=$(echo $i | cut -d: -f2)
|
||||
if sudo iptables -C load_balancer -p tcp -d $pubIp --dport $dport -j ACL_INBOUND_$dev 2>/dev/null
|
||||
then
|
||||
sudo iptables -D load_balancer -p tcp -d $pubIp --dport $dport -j ACL_INBOUND_$dev 2>/dev/null
|
||||
success=$?
|
||||
if [ $success -gt 0 ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
if [ "$stats" != "none" ]
|
||||
then
|
||||
local pubIp=$(echo $stats | cut -d: -f1)
|
||||
local dport=$(echo $stats | cut -d: -f2)
|
||||
local dport=$(echo $stats | cut -d: -f2)
|
||||
local cidrs=$(echo $stats | cut -d: -f3 | sed 's/-/,/')
|
||||
sudo iptables -F lb_stats
|
||||
sudo iptables -A lb_stats -s $cidrs -p tcp -d $pubIp --dport $dport -j ACCEPT 2>/dev/null
|
||||
success=$?
|
||||
fi
|
||||
|
|
@ -117,13 +135,14 @@ fw_entry() {
|
|||
fw_restore
|
||||
else
|
||||
fw_remove_backup
|
||||
fi
|
||||
fi
|
||||
return $success
|
||||
}
|
||||
|
||||
#Hot reconfigure HA Proxy in the routing domain
|
||||
reconfig_lb() {
|
||||
/root/reconfigLB.sh
|
||||
logger -t cloud "running reconfigLB.sh -d $1"
|
||||
/root/reconfigLB_vpc -d $1
|
||||
return $?
|
||||
}
|
||||
|
||||
|
|
@ -131,12 +150,12 @@ reconfig_lb() {
|
|||
restore_lb() {
|
||||
logger -t cloud "Restoring HA Proxy to previous state"
|
||||
# Copy the old version of haproxy.cfg into the file that reconfigLB.sh uses
|
||||
cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg.new
|
||||
|
||||
# cp /etc/haproxy/haproxy.cfg.old /etc/haproxy/haproxy.cfg.new
|
||||
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
# Run reconfigLB.sh again
|
||||
/root/reconfigLB.sh
|
||||
/root/reconfigLB_vpc -R
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +185,7 @@ do
|
|||
esac
|
||||
done
|
||||
|
||||
logger -t cloud "haproxy: i=$ip a=$addedIps d=$removedIps s=$statsIp"
|
||||
|
||||
dev=$(getEthByIp $ip)
|
||||
|
||||
|
|
@ -180,7 +200,7 @@ then
|
|||
fi
|
||||
|
||||
# hot reconfigure haproxy
|
||||
reconfig_lb
|
||||
reconfig_lb $removedIps
|
||||
|
||||
if [ $? -gt 0 ]
|
||||
then
|
||||
|
|
@ -190,12 +210,12 @@ fi
|
|||
|
||||
# iptables entry to ensure that haproxy receives traffic
|
||||
fw_entry $addedIps $removedIps $statsIp
|
||||
result=$?
|
||||
result=$?
|
||||
if [ $result -gt 0 ]
|
||||
then
|
||||
logger -t cloud "Failed to apply firewall rules for load balancing, reverting HA Proxy config"
|
||||
# Restore the LB
|
||||
restore_lb
|
||||
fi
|
||||
|
||||
|
||||
unlock_exit $result $lock $locked
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
#!/usr/bin/perl
|
||||
# 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.
|
||||
|
||||
# @VERSION@
|
||||
|
||||
use strict;
|
||||
use Getopt::Std;
|
||||
my $debug = 0;
|
||||
|
||||
my $opts = {};
|
||||
getopts('d:R',$opts);
|
||||
|
||||
my @removedips = split(/,/,$opts->{d});
|
||||
|
||||
# remove trailing colons from ip/port entries, if exists
|
||||
removecolon(\@removedips);
|
||||
|
||||
if($opts->{R}){
|
||||
# restore .save file if -R was passed in
|
||||
`mv -f /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.reverted`;
|
||||
`mv /etc/haproxy/haproxy.cfg.save /etc/haproxy/haproxy.cfg`;
|
||||
} else {
|
||||
# merge passed config with current config
|
||||
logger("reconfigLB got removedips=$opts->{d}");
|
||||
`mv -f /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.save`;
|
||||
open(FILE,">/etc/haproxy/haproxy.cfg");
|
||||
print FILE generate_config();
|
||||
close FILE;
|
||||
}
|
||||
|
||||
# graceful restart
|
||||
`mv /var/run/haproxy.pid /var/run/haproxy.pid.old`;
|
||||
my $oldpid = `cat /var/run/haproxy.pid.old`;
|
||||
|
||||
`kill -TTOU $oldpid`;
|
||||
sleep 2;
|
||||
|
||||
`haproxy -D -p /var/run/haproxy.pid -f /etc/haproxy/haproxy.cfg`;
|
||||
if ($? == 0) {
|
||||
logger("New haproxy instance successfully loaded, stopping previous one.");
|
||||
`kill -KILL $oldpid`;
|
||||
`rm -f /var/run/haproxy.pid.old`;
|
||||
exit 0;
|
||||
} else {
|
||||
logger("New instance failed to start, resuming previous one.");
|
||||
`kill -TTIN $oldpid`;
|
||||
`rm -f /var/run/haproxy.pid`;
|
||||
`mv /var/run/haproxy.pid.old /var/run/haproxy.pid`;
|
||||
`mv -f /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.newfail`;
|
||||
`mv /etc/haproxy/haproxy.cfg.save /etc/haproxy/haproxy.cfg`;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
########### subs ###########
|
||||
|
||||
sub generate_config {
|
||||
|
||||
my $config;
|
||||
|
||||
open (NEWFILE, "/etc/haproxy/haproxy.cfg.new");
|
||||
open (CURFILE, "/etc/haproxy/haproxy.cfg.save");
|
||||
|
||||
# read in new config
|
||||
my $sections = {};
|
||||
my $section;
|
||||
while (my $line = <NEWFILE>) {
|
||||
$section = $line if $line =~ /^\w/;
|
||||
print "found line for section $section\n" if $debug;
|
||||
push @{$sections->{$section}},$line;
|
||||
}
|
||||
|
||||
close NEWFILE;
|
||||
|
||||
# fetch old config
|
||||
my $oldsections = {};
|
||||
my $oldsection;
|
||||
while (my $line = <CURFILE>){
|
||||
$oldsection = $line if $line =~ /^\w/;
|
||||
|
||||
# skip default, global, and stats lines, we always want the latest
|
||||
next if $oldsection =~ /^global/;
|
||||
next if $oldsection =~ /^default/;
|
||||
next if $oldsection =~ /^listen\sstats/;
|
||||
next if $oldsection =~ /^listen\scloud-default/;
|
||||
|
||||
# delete/skip it if it is on remove list
|
||||
my $skip = 0;
|
||||
foreach my $remip (@removedips) {
|
||||
if($oldsection =~ /^listen/ && $oldsection =~ /$remip/){
|
||||
$skip = 1;
|
||||
print "skipping line for section $oldsection since it is on remove list\n" if $debug;
|
||||
}
|
||||
}
|
||||
next if $skip;
|
||||
|
||||
push @{$oldsections->{$oldsection}},$line;
|
||||
}
|
||||
|
||||
close CURFILE;
|
||||
|
||||
# print new config
|
||||
print "############ printing new config:\n\n" if $debug;
|
||||
foreach my $section (sort keys %{$sections}) {
|
||||
foreach my $line(@{$sections->{$section}}) {
|
||||
$config .= $line;
|
||||
}
|
||||
$config .= "\n";
|
||||
}
|
||||
|
||||
# add in old config that we didn't get a new config for
|
||||
print "############ printing existing config:\n\n" if $debug;
|
||||
foreach my $oldsection (sort keys %{$oldsections}) {
|
||||
next if exists $sections->{$oldsection};
|
||||
foreach my $line(@{$oldsections->{$oldsection}}) {
|
||||
$config .= $line;
|
||||
}
|
||||
$config .= "\n";
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
sub logger {
|
||||
my $msg = shift;
|
||||
`logger -t cloud $msg`;
|
||||
}
|
||||
|
||||
sub removecolon {
|
||||
my $list = shift;
|
||||
foreach(@{$list}){
|
||||
$_ =~ s/:$//;
|
||||
}
|
||||
}
|
||||
|
|
@ -1037,22 +1037,6 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
pr + " is not supported by VPC " + vpc);
|
||||
}
|
||||
}
|
||||
|
||||
//4) Only one network in the VPC can support LB
|
||||
if (_ntwkModel.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.Lb)) {
|
||||
List<? extends Network> networks = getVpcNetworks(vpc.getId());
|
||||
for (Network network : networks) {
|
||||
if (networkId != null && network.getId() == networkId.longValue()) {
|
||||
//skip my own network
|
||||
continue;
|
||||
} else {
|
||||
if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) {
|
||||
throw new InvalidParameterValueException("LB service is already supported " +
|
||||
"by network " + network + " in VPC " + vpc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue