Skip to content

Commit 840c0a0

Browse files
committed
CLOUDSTACK-8401: Fix KVM's SG script to properly cleanup old network rules
- Router VMs don't have a chain rule with -def suffix, this fixes name and properly removes VR vms not running on a host - Before trying to remove dnats, filter empty/None elements from list - destroy_ebtables_rules should check what kind of action is request to be performed (-A for add or -D for removed) and execute based on that - Before executing any command, log it for debugging purposes - Method to cleanup bridge, may be used in future Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com> (cherry picked from commit 3925512) Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent acd9a25 commit 840c0a0

1 file changed

Lines changed: 55 additions & 50 deletions

File tree

scripts/vm/network/security_group.py

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
logpath = "/var/run/cloud/" # FIXME: Logs should reside in /var/log/cloud
3131
iptables = Command("iptables")
3232
bash = Command("/bin/bash")
33-
ebtablessave = Command("ebtables-save")
3433
ebtables = Command("ebtables")
3534
driver = "qemu:///system"
3635
cfo = configFileOps("/etc/cloudstack/agent/agent.properties")
@@ -40,6 +39,7 @@
4039
def execute(cmd):
4140
logging.debug(cmd)
4241
return bash("-c", cmd).stdout
42+
4343
def can_bridge_firewall(privnic):
4444
try:
4545
execute("which iptables")
@@ -166,43 +166,23 @@ def destroy_network_rules_for_vm(vm_name, vif=None):
166166
vmchain_default = None
167167

168168
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
169-
if vm_name.startswith('i-') or vm_name.startswith('r-'):
169+
if vm_name.startswith('i-'):
170170
vmchain_default = '-'.join(vm_name.split('-')[:-1]) + "-def"
171171

172172
destroy_ebtables_rules(vmchain, vif)
173173

174-
try:
175-
if vmchain_default != None:
176-
execute("iptables -F " + vmchain_default)
177-
except:
178-
logging.debug("Ignoring failure to delete chain " + vmchain_default)
179-
180-
try:
181-
if vmchain_default != None:
182-
execute("iptables -X " + vmchain_default)
183-
except:
184-
logging.debug("Ignoring failure to delete chain " + vmchain_default)
185-
186-
try:
187-
execute("iptables -F " + vmchain)
188-
except:
189-
logging.debug("Ignoring failure to delete chain " + vmchain)
190-
191-
try:
192-
execute("iptables -X " + vmchain)
193-
except:
194-
logging.debug("Ignoring failure to delete chain " + vmchain)
195-
196-
197-
try:
198-
execute("iptables -F " + vmchain_egress)
199-
except:
200-
logging.debug("Ignoring failure to delete chain " + vmchain_egress)
174+
chains = [vmchain_default, vmchain, vmchain_egress]
175+
for chain in filter(None, chains):
176+
try:
177+
execute("iptables -F " + chain)
178+
except:
179+
logging.debug("Ignoring failure to flush chain: " + chain)
201180

202-
try:
203-
execute("iptables -X " + vmchain_egress)
204-
except:
205-
logging.debug("Ignoring failure to delete chain " + vmchain_egress)
181+
for chain in filter(None, chains):
182+
try:
183+
execute("iptables -X " + chain)
184+
except:
185+
logging.debug("Ignoring failure to delete chain: " + chain)
206186

207187
try:
208188
execute("ipset -F " + vm_name)
@@ -213,7 +193,7 @@ def destroy_network_rules_for_vm(vm_name, vif=None):
213193
if vif is not None:
214194
try:
215195
dnats = execute("""iptables -t nat -S | awk '/%s/ { sub(/-A/, "-D", $1) ; print }'""" % vif ).split("\n")
216-
for dnat in dnats:
196+
for dnat in filter(None, dnats):
217197
try:
218198
execute("iptables -t nat " + dnat)
219199
except:
@@ -229,7 +209,6 @@ def destroy_network_rules_for_vm(vm_name, vif=None):
229209
return 'true'
230210

231211
def destroy_ebtables_rules(vm_name, vif):
232-
233212
delcmd = "ebtables -t nat -L PREROUTING | grep " + vm_name
234213
delcmds = []
235214
try:
@@ -417,14 +396,18 @@ def ebtables_rules_vmip (vmname, ips, action):
417396
vmchain_inips = vmname + "-in-ips"
418397
vmchain_outips = vmname + "-out-ips"
419398

420-
for ip in ips:
421-
logging.debug("ip = "+ip)
399+
if action and action.strip() == "-A":
400+
action = "-I"
401+
402+
for ip in filter(None, ips):
403+
logging.debug("ip = " + ip)
404+
if ip == 0 or ip == "0":
405+
continue
422406
try:
423-
execute("ebtables -t nat -I " + vmchain_inips + " -p ARP --arp-ip-src " + ip + " -j RETURN")
424-
execute("ebtables -t nat -I " + vmchain_outips + " -p ARP --arp-ip-dst " + ip + " -j RETURN")
407+
execute("ebtables -t nat " + action + " " + vmchain_inips + " -p ARP --arp-ip-src " + ip + " -j RETURN")
408+
execute("ebtables -t nat " + action + " " + vmchain_outips + " -p ARP --arp-ip-dst " + ip + " -j RETURN")
425409
except:
426-
logging.debug("Failed to program ebtables rules for secondary ip "+ ip)
427-
continue
410+
logging.debug("Failed to program ebtables rules for secondary ip %s for vm %s with action %s" % (ip, vmname, action))
428411

429412
def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname, sec_ips):
430413
if not addFWFramework(brname):
@@ -540,7 +523,7 @@ def post_default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname, dhcpS
540523
logging.debug("Failed to log default network rules, ignoring")
541524
def delete_rules_for_vm_in_bridge_firewall_chain(vmName):
542525
vm_name = vmName
543-
if vm_name.startswith('i-') or vm_name.startswith('r-'):
526+
if vm_name.startswith('i-'):
544527
vm_name = '-'.join(vm_name.split('-')[:-1]) + "-def"
545528

546529
vmchain = vm_name
@@ -599,6 +582,7 @@ def check_domid_changed(vmName):
599582
break
600583

601584
return [curr_domid, old_domid]
585+
602586
def network_rules_for_rebooted_vm(vmName):
603587
vm_name = vmName
604588
[curr_domid, old_domid] = check_domid_changed(vm_name)
@@ -623,7 +607,6 @@ def network_rules_for_rebooted_vm(vmName):
623607
brName = execute("iptables-save |grep physdev-is-bridged |grep FORWARD |grep BF |grep '\-o' |awk '{print $4}' | head -1").strip()
624608

625609
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
626-
627610
default_network_rules_systemvm(vm_name, brName)
628611
return True
629612

@@ -680,18 +663,42 @@ def get_rule_logs_for_vms():
680663
def cleanup_rules_for_dead_vms():
681664
return True
682665

666+
def cleanup_bridge(bridge):
667+
bridge_name = getBrfw(bridge)
668+
logging.debug("Cleaning old bridge chains: " + bridge_name)
669+
if not bridge_name:
670+
return True
671+
672+
# Delete iptables/bridge rules
673+
rules = execute("""iptables-save | grep %s | grep '^-A' | sed 's/-A/-D/' """ % bridge_name).split("\n")
674+
for rule in filter(None, rules):
675+
try:
676+
command = "iptables " + rule
677+
execute(command)
678+
except: pass
679+
680+
chains = [bridge_name, bridge_name+'-IN', bridge_name+'-OUT']
681+
# Flush old bridge chain
682+
for chain in chains:
683+
try:
684+
execute("iptables -F " + chain)
685+
except: pass
686+
# Remove brige chains
687+
for chain in chains:
688+
try:
689+
execute("iptables -X " + chain)
690+
except: pass
691+
return True
683692

684693
def cleanup_rules():
685694
try:
686-
chainscmd = """iptables-save | grep -P '^:(?!.*-(def|eg))' | awk '{sub(/^:/, "", $1) ; print $1}'"""
695+
chainscmd = """iptables-save | grep -P '^:(?!.*-(def|eg))' | awk '{sub(/^:/, "", $1) ; print $1}' | sort | uniq"""
687696
chains = execute(chainscmd).split('\n')
688697
cleanup = []
689698
for chain in chains:
690699
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
691700
vm_name = chain
692-
693701
result = virshdomstate(vm_name)
694-
695702
if result == None or len(result) == 0:
696703
logging.debug("chain " + chain + " does not correspond to a vm, cleaning up iptable rules")
697704
cleanup.append(vm_name)
@@ -813,7 +820,6 @@ def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif
813820
default_network_rules(vm_name, vm_id, vm_ip, vmMac, vif, brname)
814821
egressrule = 0
815822
for line in lines:
816-
817823
tokens = line.split(':')
818824
if len(tokens) != 5:
819825
continue
@@ -948,7 +954,7 @@ def getBrfw(brname):
948954
if brfwname == "":
949955
brfwname = "BF-" + brname
950956
return brfwname
951-
957+
952958
def addFWFramework(brname):
953959
try:
954960
cfo = configFileOps("/etc/sysctl.conf")
@@ -992,8 +998,6 @@ def addFWFramework(brname):
992998
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-in -j " + brfwin)
993999
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-out -j " + brfwout)
9941000
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-out " + phydev + " -j ACCEPT")
995-
996-
9971001
return True
9981002
except:
9991003
try:
@@ -1025,6 +1029,7 @@ def addFWFramework(brname):
10251029
logging.debug("No command to execute")
10261030
sys.exit(1)
10271031
cmd = args[0]
1032+
logging.debug("Executing command: " + str(cmd))
10281033
if cmd == "can_bridge_firewall":
10291034
can_bridge_firewall(args[1])
10301035
elif cmd == "default_network_rules":

0 commit comments

Comments
 (0)