Skip to content
2 changes: 2 additions & 0 deletions neutron/common/ovn/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from neutron_lib.api.definitions import auto_allocated_topology
from neutron_lib.api.definitions import availability_zone as az_def
from neutron_lib.api.definitions import default_subnetpools
from neutron_lib.api.definitions import dhcpagentscheduler
from neutron_lib.api.definitions import dns
from neutron_lib.api.definitions import dns_domain_keywords
from neutron_lib.api.definitions import dns_domain_ports
Expand Down Expand Up @@ -106,6 +107,7 @@
portbindings.ALIAS,
pbe_ext.ALIAS,
default_subnetpools.ALIAS,
dhcpagentscheduler.ALIAS,
dns.ALIAS,
external_net.ALIAS,
extra_dhcp_opt.ALIAS,
Expand Down
1 change: 1 addition & 0 deletions neutron/db/address_group_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def get_address_group(self, context, id, fields=None):
def get_address_groups(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
filters = filters or {}
pager = base_obj.Pager(sorts, limit, page_reverse, marker)
address_groups = ag_obj.AddressGroup.get_objects(
context, _pager=pager, **filters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,9 @@ def _delete_vif_mac_rules(vif, current_rules):
chain = _mac_chain_name(vif)
for rule in current_rules:
if '-i %s' % vif in rule and '--among-src' in rule:
ebtables(['-D', chain] + rule.split())
# Flush the table and recreate the default DROP rule.
ebtables(['-F', chain])
ebtables(['-A', chain, '-j', 'DROP'])


def _delete_mac_spoofing_protection(vifs, current_rules, table, chain):
Expand Down
7 changes: 3 additions & 4 deletions neutron/plugins/ml2/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1619,18 +1619,17 @@ def create_port_bulk(self, context, ports):
for port in port_list:
self._before_create_port(context, port)

port_list, net_cache = self.allocate_macs_and_ips_for_ports(
context, port_list)

try:
port_list, net_cache = self.allocate_macs_and_ips_for_ports(
context, port_list)
return self._create_port_bulk(context, port_list, net_cache)
except Exception:
with excutils.save_and_reraise_exception():
# If any issue happened allocated IP addresses needs to be
# deallocated now
for port in port_list:
self.ipam.deallocate_ips_from_port(
context, port, port['ipams'])
context, port, port.get('ipams'))

@db_api.retry_if_session_inactive()
def _create_port_bulk(self, context, port_list, network_cache):
Expand Down
34 changes: 34 additions & 0 deletions neutron/tests/unit/plugins/ml2/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
from neutron.db import provisioning_blocks
from neutron.db import securitygroups_db as sg_db
from neutron.db import segments_db
from neutron.ipam import driver
from neutron.objects import base as base_obj
from neutron.objects import ports as port_obj
from neutron.objects import router as l3_obj
Expand Down Expand Up @@ -1737,6 +1738,39 @@ def test_create_ports_bulk_with_extra_dhcp_opts(self):
ports_out = self.plugin.create_port_bulk(ctx, ports_in)
self.assertEqual(edo, ports_out[0]['extra_dhcp_opts'])

def test_create_ports_bulk_with_wrong_fixed_ips(self):
cidr = '10.0.10.0/24'
with self.network() as net:
with self.subnet(net, cidr=cidr) as snet:
net_id = net['network']['id']
data = [{'network_id': net_id,
'fixed_ips': [{'subnet_id': snet['subnet']['id'],
'ip_address': '10.0.10.100'}],
'tenant_id': snet['subnet']['tenant_id']
},
{'network_id': net_id,
'fixed_ips': [{'subnet_id': snet['subnet']['id'],
'ip_address': '10.0.20.101'}],
'tenant_id': snet['subnet']['tenant_id']
}]
res = self._create_bulk_from_list(self.fmt, 'port',
data, as_admin=True)
self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
self.assertIn('IP address 10.0.20.101 is not a valid IP for '
'the specified subnet.',
res.json['NeutronError']['message'])

ipam_driver = driver.Pool.get_instance(None, self.context)
ipam_allocator = ipam_driver.get_allocator([cidr])
with db_api.CONTEXT_READER.using(self.context):
ipam_subnet = ipam_allocator._driver.get_subnet(
snet['subnet']['id'])
allocations = ipam_subnet.subnet_manager.list_allocations(
self.context)
# There are no leftovers (e.g.: 10.0.10.100) in the
# "IpamAllocation" registers
self.assertEqual([], allocations)

def test_delete_port_no_notify_in_disassociate_floatingips(self):
ctx = context.get_admin_context()
plugin = directory.get_plugin()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
During the port bulk creation, if an IPAM allocation fails (for example, if
the IP address is outside of the subnet CIDR), the other IPAM allocations
already created are deleted before raising the exception. Fixes bug
`2039550 <https://launchpad.net/bugs/2039550>`_.
24 changes: 12 additions & 12 deletions zuul.d/tempest-multinode.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
vars:
tox_envlist: integrated-network
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch,linuxbridge
Q_AGENT: openvswitch
Expand Down Expand Up @@ -172,9 +172,9 @@
vars:
tox_envlist: integrated-network
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch,linuxbridge
Q_AGENT: openvswitch
Expand Down Expand Up @@ -266,9 +266,9 @@
devstack_plugins:
neutron: https://opendev.org/openstack/neutron.git
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
Q_ML2_TENANT_NETWORK_TYPE: vxlan
Q_ML2_PLUGIN_MECHANISM_DRIVERS: openvswitch,linuxbridge
Q_AGENT: openvswitch
Expand Down Expand Up @@ -383,9 +383,9 @@
ovn:
enable_distributed_floating_ip: True
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
Q_AGENT: ovn
ML2_L3_PLUGIN: ovn-router,trunk
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
Expand Down
12 changes: 6 additions & 6 deletions zuul.d/tempest-singlenode.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,9 @@
neutron_plugin_options:
is_igmp_snooping_enabled: True
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
Q_AGENT: ovn
ML2_L3_PLUGIN: ovn-router,trunk
Q_ML2_PLUGIN_MECHANISM_DRIVERS: ovn,logger
Expand Down Expand Up @@ -448,9 +448,9 @@
vars:
tox_envlist: integrated-network
devstack_localrc:
CIRROS_VERSION: 0.5.1
DEFAULT_IMAGE_NAME: cirros-0.5.1-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.1-x86_64-uec.tar.gz
CIRROS_VERSION: 0.5.2
DEFAULT_IMAGE_NAME: cirros-0.5.2-x86_64-uec
DEFAULT_IMAGE_FILE_NAME: cirros-0.5.2-x86_64-uec.tar.gz
devstack_plugins:
neutron: https://opendev.org/openstack/neutron.git
devstack_services:
Expand Down