Skip to content

Commit

Permalink
Avoid RPC calls while holding iptables lock.
Browse files Browse the repository at this point in the history
This exhibitied itself as very slow instance starts on a Canonical
test cluster. This was because do_referesh_security_group_rules()
was making rpc calls while holding the iptables lock. This refactor
avoids that while making no functional changes (I hope).

This should resolve bug 1062314.

Change-Id: I36f805bd72f7bd06082cfe96c58d637203bcffb7
  • Loading branch information
mikalstill committed Oct 11, 2012
1 parent f54cf7b commit ba58552
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
14 changes: 13 additions & 1 deletion nova/tests/test_libvirt.py
Expand Up @@ -3141,12 +3141,24 @@ def test_multinic_iptables(self):

def test_do_refresh_security_group_rules(self):
instance_ref = self._create_instance_ref()
self.mox.StubOutWithMock(self.fw,
'instance_rules')
self.mox.StubOutWithMock(self.fw,
'add_filters_for_instance',
use_mock_anything=True)

self.fw.instance_rules(instance_ref,
mox.IgnoreArg()).AndReturn((None, None))
self.fw.add_filters_for_instance(instance_ref, mox.IgnoreArg(),
mox.IgnoreArg())
self.fw.instance_rules(instance_ref,
mox.IgnoreArg()).AndReturn((None, None))
self.fw.add_filters_for_instance(instance_ref, mox.IgnoreArg(),
mox.IgnoreArg())
self.mox.ReplayAll()

self.fw.prepare_instance_filter(instance_ref, mox.IgnoreArg())
self.fw.instances[instance_ref['id']] = instance_ref
self.mox.ReplayAll()
self.fw.do_refresh_security_group_rules("fake")

def test_unfilter_instance_undefines_nwfilter(self):
Expand Down
26 changes: 17 additions & 9 deletions nova/virt/firewall.py
Expand Up @@ -182,7 +182,8 @@ def prepare_instance_filter(self, instance, network_info):

self.instances[instance['id']] = instance
self.network_infos[instance['id']] = network_info
self.add_filters_for_instance(instance)
ipv4_rules, ipv6_rules = self.instance_rules(instance, network_info)
self.add_filters_for_instance(instance, ipv4_rules, ipv6_rules)
LOG.debug(_('Filters added to instance'), instance=instance)
self.refresh_provider_fw_rules()
LOG.debug(_('Provider Firewall Rules refreshed'), instance=instance)
Expand Down Expand Up @@ -218,7 +219,8 @@ def _add_filters(self, chain_name, ipv4_rules, ipv6_rules):
for rule in ipv6_rules:
self.iptables.ipv6['filter'].add_rule(chain_name, rule)

def add_filters_for_instance(self, instance):
def add_filters_for_instance(self, instance, inst_ipv4_rules,
inst_ipv6_rules):
network_info = self.network_infos[instance['id']]
chain_name = self._instance_chain_name(instance)
if FLAGS.use_ipv6:
Expand All @@ -227,8 +229,7 @@ def add_filters_for_instance(self, instance):
ipv4_rules, ipv6_rules = self._filters_for_instance(chain_name,
network_info)
self._add_filters('local', ipv4_rules, ipv6_rules)
ipv4_rules, ipv6_rules = self.instance_rules(instance, network_info)
self._add_filters(chain_name, ipv4_rules, ipv6_rules)
self._add_filters(chain_name, inst_ipv4_rules, inst_ipv6_rules)

def remove_filters_for_instance(self, instance):
chain_name = self._instance_chain_name(instance)
Expand Down Expand Up @@ -430,15 +431,22 @@ def refresh_instance_security_rules(self, instance):
self.iptables.apply()

@utils.synchronized('iptables', external=True)
def _inner_do_refresh_rules(self, instance, ipv4_rules,
ipv6_rules):
self.remove_filters_for_instance(instance)
self.add_filters_for_instance(instance, ipv4_rules, ipv6_rules)

def do_refresh_security_group_rules(self, security_group):
for instance in self.instances.values():
self.remove_filters_for_instance(instance)
self.add_filters_for_instance(instance)
network_info = self.network_infos[instance['id']]
ipv4_rules, ipv6_rules = self.instance_rules(instance,
network_info)
self._inner_do_refresh_rules(instance, ipv4_rules, ipv6_rules)

@utils.synchronized('iptables', external=True)
def do_refresh_instance_rules(self, instance):
self.remove_filters_for_instance(instance)
self.add_filters_for_instance(instance)
network_info = self.network_infos[instance['id']]
ipv4_rules, ipv6_rules = self.instance_rules(instance, network_info)
self._inner_do_refresh_rules(instance, ipv4_rules, ipv6_rules)

def refresh_provider_fw_rules(self):
"""See :class:`FirewallDriver` docs."""
Expand Down

0 comments on commit ba58552

Please sign in to comment.