Skip to content

Commit 7e93f33

Browse files
committed
kvm: Aqcuire lock when running security group Python script
It could happen that when multiple instances are starting at the same time on a KVM host the Agent spawns multiple instances of security_group.py which both try to modify iptables/ebtables rules. This fails with on of the two processes failing. The instance is still started, but it doesn't have any IP connectivity due to the failed programming of the security groups. This modification lets the script aqcuire a exclusive lock on a file so that only one instance of the scripts talks to iptables/ebtables at once. Other instances of the script which start will poll every 100ms if they can obtain the lock and otherwise execute anyway after 10 seconds.
1 parent 7017a82 commit 7e93f33

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

scripts/vm/network/security_group.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@
2626
from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
2727
import re
2828
import libvirt
29+
import fcntl
30+
import time
2931

3032
logpath = "/var/run/cloud/" # FIXME: Logs should reside in /var/log/cloud
33+
lock_file = "/var/lock/cloudstack_security_group.lock"
3134
iptables = Command("iptables")
3235
bash = Command("/bin/bash")
3336
ebtables = Command("ebtables")
@@ -36,6 +39,18 @@
3639
hyper = cfo.getEntry("hypervisor.type")
3740
if hyper == "lxc":
3841
driver = "lxc:///"
42+
43+
lock_handle = None
44+
45+
def file_is_locked(path):
46+
global lock_handle
47+
lock_handle = open(path, 'w')
48+
try:
49+
fcntl.lockf(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
50+
return False
51+
except IOError:
52+
return True
53+
3954
def execute(cmd):
4055
logging.debug(cmd)
4156
return bash("-c", cmd).stdout
@@ -1029,6 +1044,13 @@ def addFWFramework(brname):
10291044
sys.exit(1)
10301045
cmd = args[0]
10311046
logging.debug("Executing command: " + str(cmd))
1047+
1048+
for i in range(0,100):
1049+
if file_is_locked(lock_file):
1050+
time.sleep(0.1)
1051+
else:
1052+
break
1053+
10321054
if cmd == "can_bridge_firewall":
10331055
can_bridge_firewall(args[1])
10341056
elif cmd == "default_network_rules":

0 commit comments

Comments
 (0)