Logical switch trunk vlan support

Adding support for trunk vlan for logical switches in NSX 2.2 and up
This flag can be used for guest vlan, and is mutual exclusive from
the vlan id.

Change-Id: I0d08a84df796c226678a27c29cdd1e637f356e72
This commit is contained in:
Adit Sarfaty 2017-11-09 10:50:24 +02:00
parent e55e9f1eb7
commit be6f7e2bc0
4 changed files with 94 additions and 3 deletions

View File

@ -1164,7 +1164,7 @@ class NsxLibSwitchTestCase(BaseTestResource):
self._tz_id = uuidutils.generate_uuid()
def _create_body(self, admin_state=nsx_constants.ADMIN_STATE_UP,
vlan_id=None, description=None):
vlan_id=None, description=None, trunk_vlan=None):
body = {
"transport_zone_id": self._tz_id,
"replication_mode": "MTEP",
@ -1176,6 +1176,10 @@ class NsxLibSwitchTestCase(BaseTestResource):
body['vlan'] = vlan_id
if description is not None:
body['description'] = description
if trunk_vlan:
body['vlan_trunk_spec'] = {
'vlan_ranges': [{'start': trunk_vlan[0],
'end': trunk_vlan[1]}]}
return body
def test_create_logical_switch(self):
@ -1218,6 +1222,55 @@ class NsxLibSwitchTestCase(BaseTestResource):
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_logical_switch_trunk(self):
"""Test creating switch with trunk vlan"""
ls = self.get_mocked_resource()
trunk_vlan = [10, 20]
with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
return_value='2.2.0'):
ls.create(mocks.FAKE_NAME, self._tz_id, [],
trunk_vlan_range=trunk_vlan)
data = self._create_body(trunk_vlan=trunk_vlan)
test_client.assert_json_call(
'post', ls,
'https://1.2.3.4/api/v1/logical-switches',
data=jsonutils.dumps(data, sort_keys=True),
headers=self.default_headers())
def test_create_logical_switch_trunk_not_supported(self):
"""Test creating switch with trunk vlan without the support"""
ls = self.get_mocked_resource()
trunk_vlan = [10, 20]
with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
return_value='2.0.0'):
self.assertRaises(exceptions.InvalidInput,
ls.create,
mocks.FAKE_NAME, self._tz_id, [],
trunk_vlan_range=trunk_vlan)
def test_create_logical_switch_trunk_with_vlan(self):
"""Test creating switch with trunk vlan and vlan tag"""
ls = self.get_mocked_resource()
trunk_vlan = [10, 20]
with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
return_value='2.2.0'):
self.assertRaises(exceptions.InvalidInput,
ls.create,
mocks.FAKE_NAME, self._tz_id, [],
trunk_vlan_range=trunk_vlan,
vlan_id='111')
def test_create_logical_switch_illegal_trunk(self):
"""Test creating switch with illegal trunk vlan"""
ls = self.get_mocked_resource()
trunk_vlan = [10]
with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
return_value='2.2.0'):
self.assertRaises(exceptions.InvalidInput,
ls.create,
mocks.FAKE_NAME, self._tz_id, [],
trunk_vlan_range=trunk_vlan)
def test_delete_resource(self):
"""Test deleting switch"""
super(NsxLibSwitchTestCase, self).test_delete_resource(

View File

@ -274,7 +274,8 @@ class NsxLib(NsxLibBase):
# Features available since 2.2
if (feature == nsx_constants.FEATURE_VLAN_ROUTER_INTERFACE or
feature == nsx_constants.FEATURE_IPSEC_VPN or
feature == nsx_constants.FEATURE_ON_BEHALF_OF):
feature == nsx_constants.FEATURE_ON_BEHALF_OF or
feature == nsx_constants.FEATURE_TRUNK_VLAN):
return True
if (version.LooseVersion(self.get_version()) >=

View File

@ -121,7 +121,9 @@ class NsxLibLogicalSwitch(utils.NsxLibApiBase):
def create(self, display_name, transport_zone_id, tags,
replication_mode=nsx_constants.MTEP,
admin_state=True, vlan_id=None, ip_pool_id=None,
mac_pool_id=None, description=None):
mac_pool_id=None, description=None,
trunk_vlan_range=None):
operation = "Create logical switch"
# TODO(salv-orlando): Validate Replication mode and admin_state
# NOTE: These checks might be moved to the API client library if one
# that performs such checks in the client is available
@ -138,6 +140,40 @@ class NsxLibLogicalSwitch(utils.NsxLibApiBase):
if vlan_id:
body['vlan'] = vlan_id
# trunk_vlan_range is mutually exclusive with vlan_id
# For guest vlan tagging it is allowed for overlay networks
# TODO(asarfaty): check network type? different for ENS?
if trunk_vlan_range:
failed = False
if (self.nsxlib and
self.nsxlib.feature_supported(
nsx_constants.FEATURE_TRUNK_VLAN)):
if vlan_id is not None:
failed = True
LOG.error("Failed to create logical switch %(name)s with "
"trunk vlan: vlan id %(vlan)s is used.",
{'name': display_name, 'vlan': vlan_id})
elif (len(trunk_vlan_range) != 2 or
trunk_vlan_range[0] > trunk_vlan_range[1]):
failed = True
LOG.error("Failed to create logical switch %(name)s with "
"trunk vlan: illegal range (%(trunk)s) is used.",
{'name': display_name,
'trunk': trunk_vlan_range})
else:
body['vlan_trunk_spec'] = {'vlan_ranges': [
{'start': trunk_vlan_range[0],
'end': trunk_vlan_range[1]}]}
else:
LOG.error("Failed to create logical switch %s with trunk "
"vlan: this feature is not supported.", display_name)
failed = True
if failed:
raise exceptions.InvalidInput(
operation=operation,
arg_val=trunk_vlan_range,
arg_name='trunk_vlan_range')
if ip_pool_id:
body['ip_pool_id'] = ip_pool_id

View File

@ -137,3 +137,4 @@ FEATURE_NSX_POLICY = 'NSX Policy'
FEATURE_VLAN_ROUTER_INTERFACE = 'VLAN Router Interface'
FEATURE_IPSEC_VPN = 'IPSec VPN'
FEATURE_ON_BEHALF_OF = 'On Behalf Of'
FEATURE_TRUNK_VLAN = 'Trunk Vlan'