Merge "Add support for the multiprovider API to ML2"

This commit is contained in:
Jenkins 2013-09-05 06:01:30 +00:00 committed by Gerrit Code Review
commit 0f5e2bd607
2 changed files with 162 additions and 26 deletions

View File

@ -29,6 +29,7 @@ from neutron.db import l3_gwmode_db
from neutron.db import models_v2
from neutron.db import quota_db # noqa
from neutron.db import securitygroups_rpc_base as sg_db_rpc
from neutron.extensions import multiprovidernet as mpnet
from neutron.extensions import portbindings
from neutron.extensions import providernet as provider
from neutron.openstack.common import excutils
@ -77,7 +78,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
_supported_extension_aliases = ["provider", "router", "extraroute",
"binding", "quotas", "security-group",
"agent", "l3_agent_scheduler",
"dhcp_agent_scheduler", "ext-gw-mode"]
"dhcp_agent_scheduler", "ext-gw-mode",
"multi-provider"]
@property
def supported_extension_aliases(self):
@ -123,25 +125,48 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
fanout=False)
self.conn.consume_in_thread()
def _process_provider_create(self, context, attrs):
network_type = self._get_attribute(attrs, provider.NETWORK_TYPE)
physical_network = self._get_attribute(attrs,
def _process_provider_segment(self, segment):
network_type = self._get_attribute(segment, provider.NETWORK_TYPE)
physical_network = self._get_attribute(segment,
provider.PHYSICAL_NETWORK)
segmentation_id = self._get_attribute(attrs, provider.SEGMENTATION_ID)
segmentation_id = self._get_attribute(segment,
provider.SEGMENTATION_ID)
if attributes.is_attr_set(network_type):
segment = {api.NETWORK_TYPE: network_type,
api.PHYSICAL_NETWORK: physical_network,
api.SEGMENTATION_ID: segmentation_id}
self.type_manager.validate_provider_segment(segment)
return segment
if (attributes.is_attr_set(attrs.get(provider.PHYSICAL_NETWORK)) or
attributes.is_attr_set(attrs.get(provider.SEGMENTATION_ID))):
msg = _("network_type required if other provider attributes "
"specified")
raise exc.InvalidInput(error_message=msg)
msg = _("network_type required")
raise exc.InvalidInput(error_message=msg)
def _process_provider_create(self, network):
segments = []
if any(attributes.is_attr_set(network.get(f))
for f in (provider.NETWORK_TYPE, provider.PHYSICAL_NETWORK,
provider.SEGMENTATION_ID)):
# Verify that multiprovider and provider attributes are not set
# at the same time.
if attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
raise mpnet.SegmentsSetInConjunctionWithProviders()
network_type = self._get_attribute(network, provider.NETWORK_TYPE)
physical_network = self._get_attribute(network,
provider.PHYSICAL_NETWORK)
segmentation_id = self._get_attribute(network,
provider.SEGMENTATION_ID)
segments = [{provider.NETWORK_TYPE: network_type,
provider.PHYSICAL_NETWORK: physical_network,
provider.SEGMENTATION_ID: segmentation_id}]
elif attributes.is_attr_set(network.get(mpnet.SEGMENTS)):
segments = network[mpnet.SEGMENTS]
else:
return
return [self._process_provider_segment(s) for s in segments]
def _get_attribute(self, attrs, key):
value = attrs.get(key)
@ -158,9 +183,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
elif len(segments) > 1:
network[provider.NETWORK_TYPE] = TYPE_MULTI_SEGMENT
network[provider.PHYSICAL_NETWORK] = None
network[provider.SEGMENTATION_ID] = None
network[mpnet.SEGMENTS] = [
{provider.NETWORK_TYPE: segment[api.NETWORK_TYPE],
provider.PHYSICAL_NETWORK: segment[api.PHYSICAL_NETWORK],
provider.SEGMENTATION_ID: segment[api.SEGMENTATION_ID]}
for segment in segments]
else:
segment = segments[0]
network[provider.NETWORK_TYPE] = segment[api.NETWORK_TYPE]
@ -260,23 +287,26 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
# TODO(apech): Need to override bulk operations
def create_network(self, context, network):
attrs = network['network']
segment = self._process_provider_create(context, attrs)
tenant_id = self._get_tenant_id_for_create(context, attrs)
net_data = network['network']
segments = self._process_provider_create(net_data)
tenant_id = self._get_tenant_id_for_create(context, net_data)
session = context.session
with session.begin(subtransactions=True):
self._ensure_default_security_group(context, tenant_id)
if segment:
self.type_manager.reserve_provider_segment(session, segment)
else:
segment = self.type_manager.allocate_tenant_segment(session)
result = super(Ml2Plugin, self).create_network(context, network)
id = result['id']
self._process_l3_create(context, result, attrs)
network_id = result['id']
self._process_l3_create(context, result, net_data)
# REVISIT(rkukura): Consider moving all segment management
# to TypeManager.
db.add_network_segment(session, id, segment)
if segments:
for segment in segments:
self.type_manager.reserve_provider_segment(session,
segment)
db.add_network_segment(session, network_id, segment)
else:
segment = self.type_manager.allocate_tenant_segment(session)
db.add_network_segment(session, network_id, segment)
self._extend_network_dict_provider(context, result)
mech_context = driver_context.NetworkContext(self, context,
result)

View File

@ -13,8 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from neutron.extensions import multiprovidernet as mpnet
from neutron.extensions import portbindings
from neutron.plugins.ml2 import config as config
from neutron.extensions import providernet as pnet
from neutron.plugins.ml2 import config
from neutron.tests.unit import _test_extension_portbindings as test_bindings
from neutron.tests.unit import test_db_plugin as test_plugin
from neutron.tests.unit import test_extension_ext_gw_mode
@ -34,7 +36,12 @@ class Ml2PluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase):
# driver apis.
config.cfg.CONF.set_override('mechanism_drivers',
['logger', 'test'],
'ml2')
group='ml2')
self.physnet = 'physnet1'
self.vlan_range = '1:100'
self.phys_vrange = ':'.join([self.physnet, self.vlan_range])
config.cfg.CONF.set_override('network_vlan_ranges', [self.phys_vrange],
group='ml2_type_vlan')
self.addCleanup(config.cfg.CONF.reset)
super(Ml2PluginV2TestCase, self).setUp(PLUGIN_NAME)
self.port_create_status = 'DOWN'
@ -89,3 +96,102 @@ class TestMl2PortBindingHost(Ml2PluginV2TestCase,
class TestMl2ExtGwModeSupport(Ml2PluginV2TestCase,
test_extension_ext_gw_mode.ExtGwModeTestCase):
pass
class TestMultiSegmentNetworks(Ml2PluginV2TestCase):
def setUp(self, plugin=None):
super(TestMultiSegmentNetworks, self).setUp()
def test_create_network_provider(self):
data = {'network': {'name': 'net1',
pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1,
'tenant_id': 'tenant_one'}}
network_req = self.new_create_request('networks', data)
network = self.deserialize(self.fmt,
network_req.get_response(self.api))
self.assertEqual(network['network'][pnet.NETWORK_TYPE], 'vlan')
self.assertEqual(network['network'][pnet.PHYSICAL_NETWORK], 'physnet1')
self.assertEqual(network['network'][pnet.SEGMENTATION_ID], 1)
self.assertNotIn(mpnet.SEGMENTS, network['network'])
def test_create_network_single_multiprovider(self):
data = {'network': {'name': 'net1',
mpnet.SEGMENTS:
[{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1}],
'tenant_id': 'tenant_one'}}
net_req = self.new_create_request('networks', data)
network = self.deserialize(self.fmt, net_req.get_response(self.api))
self.assertEqual(network['network'][pnet.NETWORK_TYPE], 'vlan')
self.assertEqual(network['network'][pnet.PHYSICAL_NETWORK], 'physnet1')
self.assertEqual(network['network'][pnet.SEGMENTATION_ID], 1)
self.assertNotIn(mpnet.SEGMENTS, network['network'])
# Tests get_network()
net_req = self.new_show_request('networks', network['network']['id'])
network = self.deserialize(self.fmt, net_req.get_response(self.api))
self.assertEqual(network['network'][pnet.NETWORK_TYPE], 'vlan')
self.assertEqual(network['network'][pnet.PHYSICAL_NETWORK], 'physnet1')
self.assertEqual(network['network'][pnet.SEGMENTATION_ID], 1)
self.assertNotIn(mpnet.SEGMENTS, network['network'])
def test_create_network_multiprovider(self):
data = {'network': {'name': 'net1',
mpnet.SEGMENTS:
[{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1},
{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 2}],
'tenant_id': 'tenant_one'}}
network_req = self.new_create_request('networks', data)
network = self.deserialize(self.fmt,
network_req.get_response(self.api))
tz = network['network'][mpnet.SEGMENTS]
for tz in data['network'][mpnet.SEGMENTS]:
for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
pnet.SEGMENTATION_ID]:
self.assertEqual(tz.get(field), tz.get(field))
# Tests get_network()
net_req = self.new_show_request('networks', network['network']['id'])
network = self.deserialize(self.fmt, net_req.get_response(self.api))
tz = network['network'][mpnet.SEGMENTS]
for tz in data['network'][mpnet.SEGMENTS]:
for field in [pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK,
pnet.SEGMENTATION_ID]:
self.assertEqual(tz.get(field), tz.get(field))
def test_create_network_with_provider_and_multiprovider_fail(self):
data = {'network': {'name': 'net1',
mpnet.SEGMENTS:
[{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1}],
pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1,
'tenant_id': 'tenant_one'}}
network_req = self.new_create_request('networks', data)
res = network_req.get_response(self.api)
self.assertEqual(res.status_int, 400)
def test_create_network_duplicate_segments(self):
data = {'network': {'name': 'net1',
mpnet.SEGMENTS:
[{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1},
{pnet.NETWORK_TYPE: 'vlan',
pnet.PHYSICAL_NETWORK: 'physnet1',
pnet.SEGMENTATION_ID: 1}],
'tenant_id': 'tenant_one'}}
network_req = self.new_create_request('networks', data)
res = network_req.get_response(self.api)
self.assertEqual(res.status_int, 400)