diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-04-14 14:21:58 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-04-14 14:21:58 +0000 |
commit | cd5a0b3146f734a40bc87be36c5a67e0e5e433be (patch) | |
tree | 7b40f28f8e96cdd152391185199826fe75a48306 | |
parent | e032f09e6d37a54fa347a6503502670b63ec450f (diff) | |
parent | 68ec6840dd75dea85b6a55310c487284d7bd579e (diff) | |
download | nova-cd5a0b3146f734a40bc87be36c5a67e0e5e433be.tar.gz |
Merge "libvirt: avoid changing UUID when redefining nwfilters" into stable/icehouse
-rw-r--r-- | nova/tests/virt/libvirt/test_libvirt.py | 41 | ||||
-rw-r--r-- | nova/virt/libvirt/firewall.py | 47 |
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() |