[dvs] support 'portgroup' provider type
NSX-v plugin has support for provider network type 'portgroup'. This patch adds support for portgroup type binding in DVS plugin. Creating a portgroup type network refers to an existing dvportgroup in vSphere. Deleting this network would not delete the dvportgroup similar to NSX-v plugin. This functionality is required to import VMs on vSphere connected to an existing dvportgroup. Change-Id: I6fd1f3efdd258b5d4d5042d0f76d0a4b52cd69ee
This commit is contained in:
parent
cd041ff985
commit
6d368cb55b
@ -47,6 +47,7 @@ class NetworkTypes:
|
|||||||
FLAT = 'flat'
|
FLAT = 'flat'
|
||||||
VLAN = 'vlan'
|
VLAN = 'vlan'
|
||||||
BRIDGE = 'bridge'
|
BRIDGE = 'bridge'
|
||||||
|
PORTGROUP = 'portgroup'
|
||||||
|
|
||||||
|
|
||||||
# Allowed network types for the NSX-v Plugin
|
# Allowed network types for the NSX-v Plugin
|
||||||
|
@ -1 +1 @@
|
|||||||
c644ec62c585
|
5e564e781d77
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
# Copyright 2016 VMware, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""add nsx binding type
|
||||||
|
|
||||||
|
Revision ID: 5e564e781d77
|
||||||
|
Revises: c644ec62c585
|
||||||
|
Create Date: 2016-06-27 23:58:22.003350
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '5e564e781d77'
|
||||||
|
down_revision = 'c644ec62c585'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
tz_binding_type_enum = sa.Enum('flat', 'vlan', 'stt', 'gre', 'l3_ext',
|
||||||
|
'vxlan',
|
||||||
|
name='tz_network_bindings_binding_type')
|
||||||
|
new_tz_binding_type_enum = sa.Enum('flat', 'vlan', 'stt', 'gre', 'l3_ext',
|
||||||
|
'vxlan', 'portgroup',
|
||||||
|
name='tz_network_bindings_binding_type')
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.alter_column(
|
||||||
|
'tz_network_bindings',
|
||||||
|
'binding_type',
|
||||||
|
type_=new_tz_binding_type_enum,
|
||||||
|
existing_type=tz_binding_type_enum,
|
||||||
|
existing_nullable=False)
|
@ -42,9 +42,9 @@ class TzNetworkBinding(model_base.BASEV2):
|
|||||||
network_id = sa.Column(sa.String(36),
|
network_id = sa.Column(sa.String(36),
|
||||||
sa.ForeignKey('networks.id', ondelete="CASCADE"),
|
sa.ForeignKey('networks.id', ondelete="CASCADE"),
|
||||||
primary_key=True)
|
primary_key=True)
|
||||||
# 'flat', 'vlan', 'stt', 'gre', 'l3_ext', 'vxlan'
|
# 'flat', 'vlan', 'stt', 'gre', 'l3_ext', 'vxlan', 'portgroup'
|
||||||
binding_type = sa.Column(sa.Enum('flat', 'vlan', 'stt', 'gre', 'l3_ext',
|
binding_type = sa.Column(sa.Enum('flat', 'vlan', 'stt', 'gre', 'l3_ext',
|
||||||
'vxlan',
|
'vxlan', 'portgroup',
|
||||||
name='tz_network_bindings_binding_type'),
|
name='tz_network_bindings_binding_type'),
|
||||||
nullable=False, primary_key=True)
|
nullable=False, primary_key=True)
|
||||||
phy_uuid = sa.Column(sa.String(36), primary_key=True, default='')
|
phy_uuid = sa.Column(sa.String(36), primary_key=True, default='')
|
||||||
|
@ -117,7 +117,8 @@ class DvsManager(object):
|
|||||||
val, ['name'])
|
val, ['name'])
|
||||||
if len(props) and hasattr(props[0], 'propSet'):
|
if len(props) and hasattr(props[0], 'propSet'):
|
||||||
for prop in props[0].propSet:
|
for prop in props[0].propSet:
|
||||||
if net_id == prop.val:
|
# match name or mor id
|
||||||
|
if net_id == prop.val or net_id == val.value:
|
||||||
# NOTE(garyk): update cache
|
# NOTE(garyk): update cache
|
||||||
return val
|
return val
|
||||||
raise exceptions.NetworkNotFound(net_id=net_id)
|
raise exceptions.NetworkNotFound(net_id=net_id)
|
||||||
|
@ -146,6 +146,11 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
vlan_tag = 0
|
vlan_tag = 0
|
||||||
if net_data.get(pnet.NETWORK_TYPE) == c_utils.NetworkTypes.VLAN:
|
if net_data.get(pnet.NETWORK_TYPE) == c_utils.NetworkTypes.VLAN:
|
||||||
vlan_tag = net_data.get(pnet.SEGMENTATION_ID, 0)
|
vlan_tag = net_data.get(pnet.SEGMENTATION_ID, 0)
|
||||||
|
|
||||||
|
if net_data.get(pnet.NETWORK_TYPE) == c_utils.NetworkTypes.PORTGROUP:
|
||||||
|
net_id = net_data.get(pnet.PHYSICAL_NETWORK)
|
||||||
|
dvs_id = self._dvs._net_id_to_moref(net_id).value
|
||||||
|
else:
|
||||||
dvs_id = self._dvs_get_id(net_data)
|
dvs_id = self._dvs_get_id(net_data)
|
||||||
self._dvs.add_port_group(dvs_id, vlan_tag)
|
self._dvs.add_port_group(dvs_id, vlan_tag)
|
||||||
|
|
||||||
@ -165,6 +170,8 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.exception(_LE('Failed to create network'))
|
LOG.exception(_LE('Failed to create network'))
|
||||||
|
if (net_data.get(pnet.NETWORK_TYPE) !=
|
||||||
|
c_utils.NetworkTypes.PORTGROUP):
|
||||||
self._dvs.delete_port_group(dvs_id)
|
self._dvs.delete_port_group(dvs_id)
|
||||||
|
|
||||||
new_net[pnet.NETWORK_TYPE] = net_data.get(pnet.NETWORK_TYPE)
|
new_net[pnet.NETWORK_TYPE] = net_data.get(pnet.NETWORK_TYPE)
|
||||||
@ -189,15 +196,16 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
"network")
|
"network")
|
||||||
raise n_exc.InvalidInput(error_message=err_msg)
|
raise n_exc.InvalidInput(error_message=err_msg)
|
||||||
err_msg = None
|
err_msg = None
|
||||||
if network_type == c_utils.NetworkTypes.FLAT:
|
if (network_type == c_utils.NetworkTypes.FLAT or
|
||||||
|
network_type == c_utils.NetworkTypes.PORTGROUP):
|
||||||
if segmentation_id_set:
|
if segmentation_id_set:
|
||||||
err_msg = _("Segmentation ID cannot be specified with "
|
err_msg = (_("Segmentation ID cannot be specified with "
|
||||||
"flat network type")
|
"%s network type"), network_type)
|
||||||
elif network_type == c_utils.NetworkTypes.VLAN:
|
elif network_type == c_utils.NetworkTypes.VLAN:
|
||||||
if not segmentation_id_set:
|
if not segmentation_id_set:
|
||||||
err_msg = _("Segmentation ID must be specified with "
|
err_msg = _("Segmentation ID must be specified with "
|
||||||
"vlan network type")
|
"vlan network type")
|
||||||
elif (segmentation_id_set and
|
if (segmentation_id_set and
|
||||||
not utils.is_valid_vlan_tag(segmentation_id)):
|
not utils.is_valid_vlan_tag(segmentation_id)):
|
||||||
err_msg = (_("%(segmentation_id)s out of range "
|
err_msg = (_("%(segmentation_id)s out of range "
|
||||||
"(%(min_id)s through %(max_id)s)") %
|
"(%(min_id)s through %(max_id)s)") %
|
||||||
@ -219,10 +227,13 @@ class NsxDvsV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
def _dvs_delete_network(self, context, id):
|
def _dvs_delete_network(self, context, id):
|
||||||
network = self._get_network(context, id)
|
network = self._get_network(context, id)
|
||||||
dvs_id = self._dvs_get_id(network)
|
dvs_id = self._dvs_get_id(network)
|
||||||
|
bindings = nsx_db.get_network_bindings(context.session, id)
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
nsx_db.delete_network_bindings(context.session, id)
|
nsx_db.delete_network_bindings(context.session, id)
|
||||||
super(NsxDvsV2, self).delete_network(context, id)
|
super(NsxDvsV2, self).delete_network(context, id)
|
||||||
try:
|
try:
|
||||||
|
if (not bindings or
|
||||||
|
bindings[0].binding_type != c_utils.NetworkTypes.PORTGROUP):
|
||||||
self._dvs.delete_port_group(dvs_id)
|
self._dvs.delete_port_group(dvs_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception(_LE('Unable to delete DVS port group %s'), id)
|
LOG.exception(_LE('Unable to delete DVS port group %s'), id)
|
||||||
|
@ -161,7 +161,8 @@ class NeutronSimpleDvsTest(test_plugin.NeutronDbPluginV2TestCase):
|
|||||||
params['arg_list'] = tuple(params.keys())
|
params['arg_list'] = tuple(params.keys())
|
||||||
with mock.patch.object(self._plugin._dvs,
|
with mock.patch.object(self._plugin._dvs,
|
||||||
'add_port_group') as mock_add,\
|
'add_port_group') as mock_add,\
|
||||||
mock.patch.object(self._plugin._dvs, 'delete_port_group'):
|
mock.patch.object(self._plugin._dvs,
|
||||||
|
'delete_port_group') as mock_delete:
|
||||||
with self.network(**params) as network:
|
with self.network(**params) as network:
|
||||||
ctx = context.get_admin_context()
|
ctx = context.get_admin_context()
|
||||||
id = network['network']['id']
|
id = network['network']['id']
|
||||||
@ -175,9 +176,16 @@ class NeutronSimpleDvsTest(test_plugin.NeutronDbPluginV2TestCase):
|
|||||||
elif network_type == 'vlan':
|
elif network_type == 'vlan':
|
||||||
self.assertEqual('vlan', binding[0].binding_type)
|
self.assertEqual('vlan', binding[0].binding_type)
|
||||||
self.assertEqual(vlan_tag, binding[0].vlan_id)
|
self.assertEqual(vlan_tag, binding[0].vlan_id)
|
||||||
|
elif network_type == 'portgroup':
|
||||||
|
self.assertEqual('portgroup', binding[0].binding_type)
|
||||||
|
self.assertEqual(0, binding[0].vlan_id)
|
||||||
else:
|
else:
|
||||||
self.fail()
|
self.fail()
|
||||||
|
if network_type != 'portgroup':
|
||||||
mock_add.assert_called_once_with(dvs_id, vlan_tag)
|
mock_add.assert_called_once_with(dvs_id, vlan_tag)
|
||||||
|
else:
|
||||||
|
mock_add.call_count = 0
|
||||||
|
mock_delete.call_count = 0
|
||||||
|
|
||||||
def test_create_and_delete_dvs_network_tag(self):
|
def test_create_and_delete_dvs_network_tag(self):
|
||||||
self._create_and_delete_dvs_network(network_type='vlan', vlan_tag=7)
|
self._create_and_delete_dvs_network(network_type='vlan', vlan_tag=7)
|
||||||
@ -185,6 +193,18 @@ class NeutronSimpleDvsTest(test_plugin.NeutronDbPluginV2TestCase):
|
|||||||
def test_create_and_delete_dvs_network_flat(self):
|
def test_create_and_delete_dvs_network_flat(self):
|
||||||
self._create_and_delete_dvs_network()
|
self._create_and_delete_dvs_network()
|
||||||
|
|
||||||
|
@mock.patch.object(dvs.DvsManager, '_net_id_to_moref')
|
||||||
|
def test_create_and_delete_dvs_network_portgroup(self, fake_get_moref):
|
||||||
|
self._create_and_delete_dvs_network(network_type='portgroup')
|
||||||
|
self.assertTrue(fake_get_moref.call_count)
|
||||||
|
|
||||||
|
@mock.patch.object(dvs.DvsManager, '_net_id_to_moref')
|
||||||
|
def test_create_and_delete_dvs_network_portgroup_vlan(self,
|
||||||
|
fake_get_moref):
|
||||||
|
self._create_and_delete_dvs_network(network_type='portgroup',
|
||||||
|
vlan_tag=7)
|
||||||
|
self.assertTrue(fake_get_moref.call_count)
|
||||||
|
|
||||||
def test_create_and_delete_dvs_port(self):
|
def test_create_and_delete_dvs_port(self):
|
||||||
params = {'provider:network_type': 'vlan',
|
params = {'provider:network_type': 'vlan',
|
||||||
'provider:physical_network': 'dvs',
|
'provider:physical_network': 'dvs',
|
||||||
|
Loading…
Reference in New Issue
Block a user