summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-04-14 14:21:58 +0000
committerGerrit Code Review <review@openstack.org>2015-04-14 14:21:58 +0000
commitcd5a0b3146f734a40bc87be36c5a67e0e5e433be (patch)
tree7b40f28f8e96cdd152391185199826fe75a48306
parente032f09e6d37a54fa347a6503502670b63ec450f (diff)
parent68ec6840dd75dea85b6a55310c487284d7bd579e (diff)
downloadnova-cd5a0b3146f734a40bc87be36c5a67e0e5e433be.tar.gz
Merge "libvirt: avoid changing UUID when redefining nwfilters" into stable/icehouse
-rw-r--r--nova/tests/virt/libvirt/test_libvirt.py41
-rw-r--r--nova/virt/libvirt/firewall.py47
2 files changed, 72 insertions, 16 deletions
diff --git a/nova/tests/virt/libvirt/test_libvirt.py b/nova/tests/virt/libvirt/test_libvirt.py
index 2478e8eea7..fad2324122 100644
--- a/nova/tests/virt/libvirt/test_libvirt.py
+++ b/nova/tests/virt/libvirt/test_libvirt.py
@@ -7470,18 +7470,33 @@ class NWFilterFakes:
def filterDefineXMLMock(self, xml):
class FakeNWFilterInternal:
- def __init__(self, parent, name, xml):
+ def __init__(self, parent, name, u, xml):
self.name = name
+ self.uuid = u
self.parent = parent
self.xml = xml
+ def XMLDesc(self, flags):
+ return self.xml
+
def undefine(self):
del self.parent.filters[self.name]
- pass
+
tree = etree.fromstring(xml)
name = tree.get('name')
+ u = tree.find('uuid')
+ if u is None:
+ u = uuid.uuid4().hex
+ else:
+ u = u.text
if name not in self.filters:
- self.filters[name] = FakeNWFilterInternal(self, name, xml)
+ self.filters[name] = FakeNWFilterInternal(self, name, u, xml)
+ else:
+ if self.filters[name].uuid != u:
+ raise libvirt.libvirtError(
+ "Mismatching name '%s' with uuid '%s' vs '%s'"
+ % (name, self.filters[name].uuid, u))
+ self.filters[name].xml = xml
return True
@@ -8022,6 +8037,26 @@ class NWFilterTestCase(test.TestCase):
db.instance_destroy(admin_ctxt, instance_ref['uuid'])
+ def test_redefining_nwfilters(self):
+ fakefilter = NWFilterFakes()
+ self.fw._conn.nwfilterDefineXML = fakefilter.filterDefineXMLMock
+ self.fw._conn.nwfilterLookupByName = fakefilter.nwfilterLookupByName
+
+ instance_ref = self._create_instance()
+ inst_id = instance_ref['id']
+ inst_uuid = instance_ref['uuid']
+
+ self.security_group = self.setup_and_return_security_group()
+
+ db.instance_add_security_group(self.context, inst_uuid,
+ self.security_group['id'])
+
+ instance = db.instance_get(self.context, inst_id)
+
+ network_info = _fake_network_info(self.stubs, 1)
+ self.fw.setup_basic_filtering(instance, network_info)
+ self.fw.setup_basic_filtering(instance, network_info)
+
def test_nwfilter_parameters(self):
admin_ctxt = context.get_admin_context()
diff --git a/nova/virt/libvirt/firewall.py b/nova/virt/libvirt/firewall.py
index 00c0946c72..e86ba6c05e 100644
--- a/nova/virt/libvirt/firewall.py
+++ b/nova/virt/libvirt/firewall.py
@@ -15,6 +15,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import uuid
+
+from lxml import etree
from oslo.config import cfg
from nova.cloudpipe import pipelib
@@ -59,31 +62,30 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
return self._libvirt_get_connection()
_conn = property(_get_connection)
- @staticmethod
- def nova_no_nd_reflection_filter():
+ def nova_no_nd_reflection_filter(self):
"""This filter protects false positives on IPv6 Duplicate Address
Detection(DAD).
"""
+ uuid = self._get_filter_uuid('nova-no-nd-reflection')
return '''<filter name='nova-no-nd-reflection' chain='ipv6'>
<!-- no nd reflection -->
<!-- drop if destination mac is v6 mcast mac addr and
we sent it. -->
-
+ <uuid>%s</uuid>
<rule action='drop' direction='in'>
<mac dstmacaddr='33:33:00:00:00:00'
dstmacmask='ff:ff:00:00:00:00' srcmacaddr='$MAC'/>
</rule>
- </filter>'''
+ </filter>''' % uuid
- @staticmethod
- def nova_dhcp_filter():
+ def nova_dhcp_filter(self):
"""The standard allow-dhcp-server filter is an <ip> one, so it uses
ebtables to allow traffic through. Without a corresponding rule in
iptables, it'll get blocked anyway.
"""
-
+ uuid = self._get_filter_uuid('nova-allow-dhcp-server')
return '''<filter name='nova-allow-dhcp-server' chain='ipv4'>
- <uuid>891e4787-e5c0-d59b-cbd6-41bc3c6b36fc</uuid>
+ <uuid>%s</uuid>
<rule action='accept' direction='out'
priority='100'>
<udp srcipaddr='0.0.0.0'
@@ -97,7 +99,7 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
srcportstart='67'
dstportstart='68'/>
</rule>
- </filter>'''
+ </filter>''' % uuid
def setup_basic_filtering(self, instance, network_info):
"""Set up basic filtering (MAC, IP, and ARP spoofing protection)."""
@@ -172,7 +174,9 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
nic_id = vif['address'].replace(':', '')
instance_filter_name = self._instance_filter_name(instance, nic_id)
parameters = self._get_instance_filter_parameters(vif)
+ uuid = self._get_filter_uuid(instance_filter_name)
xml = '''<filter name='%s' chain='root'>''' % instance_filter_name
+ xml += '<uuid>%s</uuid>' % uuid
for f in filters:
xml += '''<filterref filter='%s'>''' % f
xml += ''.join(parameters)
@@ -210,23 +214,40 @@ class NWFilterFirewall(base_firewall.FirewallDriver):
filter_set = ['no-mac-spoofing',
'no-ip-spoofing',
'no-arp-spoofing']
- self._define_filter(self.nova_no_nd_reflection_filter)
+
+ self._define_filter(self.nova_no_nd_reflection_filter())
filter_set.append('nova-no-nd-reflection')
self._define_filter(self._filter_container('nova-nodhcp', filter_set))
filter_set.append('allow-dhcp-server')
self._define_filter(self._filter_container('nova-base', filter_set))
self._define_filter(self._filter_container('nova-vpn',
['allow-dhcp-server']))
- self._define_filter(self.nova_dhcp_filter)
+ self._define_filter(self.nova_dhcp_filter())
self.static_filters_configured = True
def _filter_container(self, name, filters):
- xml = '''<filter name='%s' chain='root'>%s</filter>''' % (
- name,
+ uuid = self._get_filter_uuid(name)
+ xml = '''<filter name='%s' chain='root'>
+ <uuid>%s</uuid>
+ %s
+ </filter>''' % (name, uuid,
''.join(["<filterref filter='%s'/>" % (f,) for f in filters]))
return xml
+ def _get_filter_uuid(self, name):
+ try:
+ flt = self._conn.nwfilterLookupByName(name)
+ xml = flt.XMLDesc(0)
+ doc = etree.fromstring(xml)
+ u = doc.find("./uuid").text
+ except Exception as e:
+ LOG.debug("Cannot find UUID for filter '%s': '%s'" % (name, e))
+ u = uuid.uuid4().hex
+
+ LOG.debug("UUID for filter '%s' is '%s'" % (name, u))
+ return u
+
def _define_filter(self, xml):
if callable(xml):
xml = xml()